以下面的代码为例,以确定类型列表的长度:

template <class... Types>
class type_list {};

template <class TypeList>
struct type_list_length;  // <---

template <template <class...> class type_list, class... Types>
struct type_list_length<TypeList<Types...>>
{
    static constexpr std::size_t value = sizeof...(Types);
};

Godbolt

为什么需要标记的声明?我试图在几个编译器中编译没有它的代码,但是总是会出错。

最佳答案



因为您使用class如下

std::cout << type_list_length<type_list<int, long, long long>>::value;
// ...........................^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- template argument

或者也
std::cout << type_list_length<std::tuple<int, long, long long>>::value;
// ...........................^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ <- template argumen

或以类似方式。

观察模板参数:在两种情况下都是类型;第一种情况下为type_list<int, long, long long>,即std::tuple<int, long, long long>

因此,您不能将type_list_length声明为接收模板模板类型
template <template <class...> class type_list, class... Types>
struct type_list_length // <--- doesn't work
{
    static constexpr std::size_t value = sizeof...(Types);
};

因为您应该通过传递template-template参数和可变的模板列表来调用它;我的意思是...您应该按以下方式使用它
std::cout << type_list_length<type_list, int, long, long long>::value;
std::cout << type_list_length<std::tuple, int, long, long long>::value;

但是,通过这种方式,您失去了类的功能:提取并计算类型参数的模板参数。

因此,您首先需要声明type_list_length为接收类型
template <typename> // no template parameter name needed here (not used)
struct type_list_length;

然后在接收到的类型是带有参数的模板模板的情况下声明并定义一个特殊化
template <template <typename...> class type_list, typename... Types>
struct type_list_length<TypeList<Types...>>
{ // ...................^^^^^^^^^^^^^^^^^^   the parameter is a type
    static constexpr std::size_t value = sizeof...(Types);
};

关于c++ - 为什么我们需要对template-template参数进行模板特化,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/56875637/

10-15 01:14
查看更多