SFINAE to check "template template class" (in template argument) elegantly
c++, c++14, sfinae, template-templates
Solution
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>> {
}
Problem
How to check type of a template template class in template argument? Example `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(){ } ```