SFINAE to check the template template class (in the template argument) elegantly

How to check template template type in template argument?

Example

B<T>and C<T>is a 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 way ( demo ). He 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 is #1very long and ugly (use Dummyfor hacking).
In a real program, it is also error prone, especially when B<...>it C<...>can have 5-7 template arguments.

Are there any ways to improve it?
I dream of something like: -

template<class BCLocal=BC> static
    typename std::enable_if<std::is_same<BCLocal,B>::value,void>::type f(){ 
}
+4
1

?

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

SFINAE f :

static auto f() -> typename std::enable_if<is_same_temp<BC, B>::value>::type {
}

void enable_if, , .

trailing , .


++ 14 . .

template<template<class...> class L, template<class...> class R>
using bool const is_same_temp_v = is_same_temp<L, R>::value;

std::enable_if_t:

static auto f() -> std::enable_if_t<is_same_temp_v<BC, B>> {
}
+7

Source: https://habr.com/ru/post/1676636/


All Articles