提问人:Maeglin 提问时间:6/1/2023 更新时间:6/1/2023 访问量:71
在 c++ 中调用嵌套的静态成员
Calling nested static members in c++
问:
我正在创建一个调用嵌套模板函数的程序。如果嵌套的模板函数是类成员(即通过添加 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;
}
答:
2赞
Oersted
6/1/2023
#1
你纠正它的方式,没有递归(没有函数调用自身)。
此外,静态函数只能调用静态函数(非静态函数应由对象调用)。
模板参数未声明,也未正确使用。
首先声明函数的泛型版本,该版本将接受第一个参数 () 和其他参数 ()。你似乎已经走上了这条轨道。
如果 中的参数数不为零,则可以在不指定模板参数的情况下递归:进程然后转发到同一函数:该函数将自行推导它们。
如果 中的参数数为零,则调用特殊实现。
在 C++17 之前,您将为每种情况编写一个函数,并使用 SFINAE 仅保留一个格式正确的重载。您可以通过在模板参数中添加 std::enable_if_t
来做到这一点,该参数对于单个参数大小写无效。
由于 C++17 更容易,只需编写一个带有 if constexpr
的函数,就像编写经典递归一样。
这是解决方法:head
tails
tails
head
tails
tails
#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;
}
评论
test_recursive_sub
不是静态的,因此无法从静态方法调用