How to check type of a template template class in template argument?
B<T>
and C<T>
are template class.
I want to create a class D<class BC>
that can be D<B>
or D<C>
.
Only D<B>
has D::f()
.
Here is my workaround (demo). It works.
#include <iostream>
using namespace std;
class Dummy{};
template<class T>class B{};
template<class T>class C{};
template<template<class T> class BC>class D{
//f() is instantiated only if "BC" == "B"
public: template<class BCLocal=BC<Dummy>> static
typename std::enable_if<std::is_same<BCLocal,B<Dummy>>::value,void>::type f(){
}
//^ #1
};
int main() {
D<B>::f();
//D<C>::f(); //compile error as expected, which is good
return 0;
}
The line #1
is very long and ugly (use Dummy
to hack).
In real program, it is also error-prone, especially when B<...>
and C<...>
can have 5-7 template arguments.
Are there ways to improve it?
I dream for something like :-
template<class BCLocal=BC> static
typename std::enable_if<std::is_same<BCLocal,B>::value,void>::type f(){
}
Why not just extract the comparison into a handy utility?
#include <type_traits>
template<template<class...> class L, template<class...> class R>
struct is_same_temp : std::false_type {};
template<template<class...> class T>
struct is_same_temp<T, T> : std::true_type {};
Then SFINAE on f
can simply look like this:
static auto f() -> typename std::enable_if<is_same_temp<BC, B>::value>::type {
}
There't no need to specify void
for enable_if
since it's the default type it gives.
And the trailing return type also has a prettifying effect, I think.
With C++14, we can prettify further. First a variable template.
template<template<class...> class L, template<class...> class R>
using bool const is_same_temp_v = is_same_temp<L, R>::value;
Then with the std::enable_if_t
template alias:
static auto f() -> std::enable_if_t<is_same_temp_v<BC, B>> {
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With