std :: is_same等效于非特定模板类型

kre*_*und 3 c++ templates c++11

在一个项目中,我发现有可能将DRY保留为很多代码,除了一些小部件可以保持模板的模板特化相同.这是一个小工作示例,我正在做的是检查我正在使用的模板化类:

template<typename T>
class A{};

template<typename T>
class B{};

template<template<class> class C>
void do_stuff()
{
    if(std::is_same<A<int>,C<int>>::value)
    {
    // Do Stuff for A
    } else if(std::is_same<B<int>,C<int>>::value)
    // Do Stuff for B
    }
}

int main()
{
    do_stuff<A>();
}
Run Code Online (Sandbox Code Playgroud)

我想做的是使用

std::is_same<A,C>::value
Run Code Online (Sandbox Code Playgroud)

确定模板类型.是否有任何功能可以帮助我,或者我错过了一种在这种情况下效果更好的模式?

我看到我可以做类似的事情

template<template<class> class C, typename T>
void do_stuff();

do_stuff<A,T>();
Run Code Online (Sandbox Code Playgroud)

但这对我来说似乎是错误的做法.

Tar*_*ama 6

您可以编写一个is_same_template特征,该特征部分专用于两个模板模板参数相同的时间:

template <template <typename...> class, template<typename...> class> 
struct is_same_template : std::false_type{};

template <template <typename...> class T>
struct is_same_template<T,T> : std::true_type{};
Run Code Online (Sandbox Code Playgroud)

然后你就可以写了is_same_template<A,C>::value.

请注意,这对于具有非类型模板参数的模板不起作用std::array.

某些编译器不会将别名模板视为与其别名的模板等效,因此以下结果将导致std::false_type:

template <typename T, typename Alloc>
using MyVec = std::vector<T, Alloc>;

is_same_template<std::vector, MyVec>;
Run Code Online (Sandbox Code Playgroud)

这被认为是标准中缺陷,但在所有常见编译器中实现此修复之前,不应依赖行为.


也就是说,您需要注意放在这些if分支中的内容,因为无论模板实例化的是什么,代码都需要编译.在C++ 17中,您将能够用来if constexpr解决这个问题,但是现在您需要标记调度或者如果分支具有仅对A或有效的代码,则需要具有不同的特殊化B.

template <template <typename...> class> struct tag{};

template <template <typename> class T>
void do_stuff() {
    do_stuff(tag<T>{});
}

void do_stuff(tag<A>) {
    std::cout << "A";
}

void do_stuff(tag<B>) {
    std::cout << "B";   
}
Run Code Online (Sandbox Code Playgroud)

  • 值得注意的是,根据当前的语言规则,如果一个参数是一个别名模板,比如`template <class ... Ts>,使用B = A <Ts ...>;`,`is_same_template <A,B> `将是`false_type`.很多人一开始觉得这种反直觉. (5认同)