在 c++ 中调用嵌套的静态成员

Calling nested static members in c++

提问人:Maeglin 提问时间:6/1/2023 更新时间:6/1/2023 访问量:71

问:

我正在创建一个调用嵌套模板函数的程序。如果嵌套的模板函数是类成员(即通过添加 this->template),则它可以正常工作。但是如何让它在静态情况下工作(即???)

代码示例有点复杂,但最重要的几行是在同一类中调用嵌套模板函数时 the 和静态版本之间的区别。什么必须取代???this->template test_recursive_sub<TH>(gs...);??? test_recursive_sub<TH>(gs...);

#include <cstdint>
#include <iostream>
#include <string>
#include <vector>

struct TestObject1 {
    using Type = int;
};

struct TestObject2 {
    using Type = int;
};

struct TestObject3 {
    using Type = int;
};

struct MyStruct {
    template<typename TH>
    void printno() {
        typename TH::Type num = 100;
        std::cout << num << std::endl;
    }

    template<typename TH>
    void static st_printno() {
        typename TH::Type num = 100;
        std::cout << num << std::endl;
    }

    template<typename TH, typename ... TG>
    void test_recursive_sub(TG &... gs) {
        printno<TH>();
    }

    template<typename TH, typename ... TG>
    void test_recursive(TG &... gs) {
        this->template test_recursive_sub<TH>(gs...);
    }

    template<typename TH, typename ... TGs>
    static void recursive_sub(TGs &... gs) {
        MyStruct::st_printno<TH>();
    }

    template<typename TH, typename ... TGs>
    static void static_recursive(TGs &... gs) {
        ??? test_recursive_sub<TH>(gs...);
    }
};

int static_template_nesting() {

    TestObject1 to1;
    TestObject2 to2;

    MyStruct ro1;

    ro1.test_recursive<TestObject2>(to1, to1, to2);
    ro1.test_recursive<TestObject3>(to2);
    MyStruct::static_recursive<TestObject2>(to1, to1, to2);
    MyStruct::static_recursive<TestObject3>(to2);

    return 0;
}
C++ 模板 静态 嵌套

评论

4赞 Alan Birtles 6/1/2023
test_recursive_sub不是静态的,因此无法从静态方法调用
0赞 PiotrNycz 6/1/2023
您可以使用它来调用静态方法

答:

2赞 Oersted 6/1/2023 #1

你纠正它的方式,没有递归(没有函数调用自身)。 此外,静态函数只能调用静态函数(非静态函数应由对象调用)。 模板参数未声明,也未正确使用。 首先声明函数的泛型版本,该版本将接受第一个参数 () 和其他参数 ()。你似乎已经走上了这条轨道。 如果 中的参数数不为零,则可以在不指定模板参数的情况下递归:进程然后转发到同一函数:该函数将自行推导它们。 如果 中的参数数为零,则调用特殊实现。 在 C++17 之前,您将为每种情况编写一个函数,并使用 SFINAE 仅保留一个格式正确的重载。您可以通过在模板参数中添加 std::enable_if_t 来做到这一点,该参数对于单个参数大小写无效。 由于 C++17 更容易,只需编写一个带有 if constexpr 的函数,就像编写经典递归一样。 这是解决方法:headtailstailsheadtailstails

#include <cstdint>
#include <iostream>
#include <string>
#include <vector>

// will use std::enable_if until C++14
#include <type_traits>

struct TestObject1 {
    using Type = int;
};

struct TestObject2 {
    using Type = int;
};

struct TestObject3 {
    using Type = int;
};

struct MyStruct {
    template <typename TH>
    void printno() {
        typename TH::Type num = 100;
        std::cout << num << std::endl;
    }

    template <typename TH>
    void static st_printno() {
        typename TH::Type num = 100;
        std::cout << num << std::endl;
    }

    template <typename TH, typename... TG>
    void test_recursive_sub(TG &...gs) {
        printno<TH>();
    }

    template <typename TH, typename... TG>
    void test_recursive(TG &...gs) {
        this->template test_recursive_sub<TH>(gs...);
    }

    template <typename TH, typename... TGs>
    static void recursive_sub(TGs &...gs) {
        MyStruct::st_printno<TH>();
    }

    // C++14 version
    // overload for multiple argument only
    // SFINAE will eliminate it if there is only one argument
    template <typename TH, typename... TGs,
              std::enable_if_t<(sizeof...(TGs) > 0), bool> = true>
    static void static_recursive(TH &head, TGs &...tail) {
        std::cout << "process an arg then " << sizeof...(TGs) << " args"
                  << std::endl;
        static_recursive(tail...);
    }
    template <typename TH>
    // overload for single argument only
    static void static_recursive(TH &head) {
        std::cout << "process single element" << std::endl;
    }
    // C++17 version
    // template <typename TH, typename... TGs>
    // static void static_recursive(TH &head, TGs &...tail) {
    //     if constexpr (sizeof...(TGs) > 0) {
    //         std::cout << "process an arg then " << sizeof...(TGs) << " args"
    //                   << std::endl;
    //         static_recursive(tail...);
    //     } else {
    //         std::cout << "process single element" << std::endl;
    //     }
    // }
};

int main() {
    TestObject1 to1;
    TestObject2 to2;

    MyStruct ro1;

    ro1.test_recursive<TestObject2>(to1, to1, to2);
    ro1.test_recursive<TestObject3>(to2);
    // no need to give template arguments, they are deduced
    MyStruct::static_recursive(to1, to1, to2);
    MyStruct::static_recursive(to2);

    return 0;
}