std::is_same equivalent for unspecialised template types

醉酒当歌 提交于 2021-02-09 00:22:32

问题


In one project I have found a possibility to stay DRY as a lot of code except for some small parts could stay the same for template specialisations of a template. Here is a small working example what I'm currently doing to check which templated class I'm using:

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>();
}

What I would like to do instead is using

std::is_same<A,C>::value

to determine the template type. Is there any function that could help me or am I missing a pattern that would work better in this case?

I see that I could do something like

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

do_stuff<A,T>();

but that seems like the wrong way to do for me.


回答1:


You could write an is_same_template trait which is partially specialized for when the two template template parameters are the same:

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{};

Then you can write is_same_template<A,C>::value.

Note that this won't work for templates which have non-type template parameters, like std::array.

Some compilers will not consider an alias template to be equivalent to the template it aliases, so the following would result in std::false_type:

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

is_same_template<std::vector, MyVec>;

This is considered a defect in the standard, but you shouldn't rely on behaviour until this fix is implemented in all common compilers.


That said, you need to be careful about what you put in those if branches, as the code needs to compile regardless of what the template is instantiated with. In C++17 you'll be able to use if constexpr to solve this problem, but for now you'll need to tag dispatch or have different specializations if the branches have code which is only valid for A or 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";   
}


来源:https://stackoverflow.com/questions/38630445/stdis-same-equivalent-for-unspecialised-template-types

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!