问题
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