gpt4 book ai didi

C++ 使用模板参数包调用多个模板化函数

转载 作者:搜寻专家 更新时间:2023-10-31 02:16:05 25 4
gpt4 key购买 nike

亲爱的互联网人,

我目前正在用 C++14 编写一个变体类,需要为参数包中的每个元素调用一个模板函数。经过一番搜索,我遇到了 this具有以下示例的页面。

template<typename... Ts> void func(Ts... args){
const int size = sizeof...(args) + 2;
int res[size] = {1,args...,2};
// since initializer lists guarantee sequencing, this can be used to
// call a function on each element of a pack, in order:
int dummy[sizeof...(Ts)] = { (std::cout << args, 0)... };
}

我创建了这个小示例来演示我要实现的目标。

#include <iostream>

template<typename Ta, typename Tb> struct TypeCmp
{
static constexpr bool Value = false;
};

template<typename T> struct TypeCmp<T, T>
{
static constexpr bool Value = true;
};

template<typename T, typename... Ts> struct TypeIdCounter;

template<typename T> struct TypeIdCounter<T>
{
static constexpr size_t Value = 1;
};

template<typename T, typename Tcur, typename... Ts> struct TypeIdCounter<T, Tcur, Ts...>
{
static constexpr size_t Value = sizeof(Tcur)+(TypeCmp<T, Tcur>::Value ? 0 : TypeIdCounter<T, Ts...>::Value);
};

template<typename... Ts> struct TypeHolder
{
template<typename T> struct Info
{
static constexpr size_t Id = TypeIdCounter<T, Ts...>::Value;
static constexpr size_t Size = sizeof(T);

static void Print(size_t id)
{
if (Id == id)
{
std::cout << "Type::Id = " << Id << std::endl;
std::cout << "Type::Size = " << Size << std::endl;
}
}
};

template<typename T> TypeHolder(const T& value) : id(Info<T>::Id)
{
/* copy value to container */
}

void Print() const
{
int dummy[] = {(Info<Ts>::Print(id), 0)...};
if (dummy[0])
{
/* dummy test needed! */
}
}

size_t id;
};

struct Foo
{
std::string name;
int age;
};

typedef TypeHolder<int, long long, bool, Foo> MyTypes;

int main(int argc, char* args[])
{
std::cout << "Id(int): " << MyTypes::Info<int>::Id << std::endl;
std::cout << "Id(bool): " << MyTypes::Info<bool>::Id << std::endl;
std::cout << "Id(Foo): " << MyTypes::Info<Foo>::Id << std::endl;

MyTypes types(true);

types.Print();

return 0;
}

上面列出的程序生成以下输出。

Id(int): 4
Id(bool): 13
Id(Foo): 53
Type::Id = 13
Type::Size = 1

一如既往,我用 -Wall -Werror 编译我的代码旗帜。所以 if (dummy[0])...需要条件,否则我会得到 unused variable 'dummy'错误。

我完全不知道为什么 int dummy[] = {(Info<Ts>::Print(id), 0)...};似乎自 Info::Print 开始工作是一个无效的方法。有人可以启发我并解释为什么这样做吗?有没有办法防止 int dummy[] = {(...)}; if (dummy[0]);不掉线的技巧-Wall -Werror

我一直在努力寻找解释,但因为我什至不知道这个结构叫什么,所以很难找到任何东西。

最佳答案

using dummy=int[];
(void)dummy{0,
((void)(Info<Ts>::Print(id)), 0)...
};

将取代

int dummy[] = {(Info<Ts>::Print(id), 0)...};

并且不应生成任何警告。它还处理长度为 0 的列表。

, 运算符将采用 void 类型。它是内置的,而且很神奇。

Print 旁边使用 (void) 可以确保如果 Print 的返回类型是非 void 返回类型重载 operator,(blah, 0),我们不会得到意外行为。

我自己,在支持它的编译器上,我写了 invoke_for_each

template<class T>struct tag_type{using type=T;};
template<class T>constexpr tag_type<T> tag{};

template<class F, class...Ts>
void invoke_for_each( F&& f, Ts&&...ts ) {
using dummy=int[];
(void)dummy{0,
((void)(f(std::forward<Ts>(ts)), 0)...
};
};

现在在使用点:

invoke_for_each(
[&](auto tag){
using T=typename decltype(tag)::type;
Info<T>::Print(id);
},
tag<Ts>...
);

我们将魔法阵列的东西移到阅读代码的人的视线之外。

关于C++ 使用模板参数包调用多个模板化函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37490012/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com