我的目标是编写一个简单的通用函数来注册任意 C++ 类型的转换器。为了简单起见,我将只打印 C++ 类型名称。我希望能够调用我的通用函数print_type_name
适用于任何类型的函数,包括同时使用多种类型(可变参数):
template <typename T>
void print_type_name(void)
{
std::cout << typeid(T).name() << std::endl;
}
这对于这样的事情效果很好:
print_type_name<int>();
print_type_name<std::string>();
print_type_name<std::vector<std::complex<float> > >();
但是,我需要能够为可变参数模板中的每种类型调用此函数,例如(展开时):
print_type_name<int, std::string, std::vector<std::complex<float> > >();
这是我想出的,但它相当笨重:
template <typename ...TS>
void noop(TS... ts) { }
template <typename T>
int real_print_type_name(void) {
std::cout << typeid(T).name() << std::endl;
return 0;
}
template <typename ...TS>
void print_type_name(void) {
noop(real_print_type_name<TS>()...);
}
这允许以下操作:
template <typename ...TS>
void other_function(void) {
print_type_name<TS...>();
}
注意无用的noop
函数和int
返回类型为real_print_type_name
,为了扩展我必须添加这两个内容
参数包。有没有更干净的方法来做到这一点?
这是一个辅助函数。它使用随机的黑魔法,但它的名字很清楚:
void do_in_order() {}
template<class...Fs>
void do_in_order( Fs&&...fs ) {
using discard=int[];
(void)discard{0, (void(
std::forward<Fs>(fs)()
),0)... };
}
或者在 C++17 中:
template<class...Fs>
void do_in_order( Fs&&...fs ) {
(void(std::forward<Fs>(fs)())...);
}
(好多了)。
这隐藏了任何丑陋。需要一组void()
可调用对象和调用
它们从左到右——它按顺序执行任务,就像罐头上写的那样。
Then print_type_names
变成:
template<class...Ts>
void print_type_names() {
do_in_order( print_type_name<Ts>... );
}
or
template<class...Ts>
void print_type_names() {
do_in_order( [&]{
std::cout << typeid(Ts).name() << std::endl;
}... );
}
如果你不想使用单一print_type_name
函数并想要内联它。
请注意,一些不合格的编译器抱怨将整个 lambda 扩展为...
.
活生生的例子
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)