I have a situation where I need to distinguish between two overloads, say foo , using std::enable_if . The condition specified by std::enable_if depends on the dependent type of the template parameter foo .
What is the best way to express this with std::enable_if ?
The following test code is what I have. I understand that there are probably better ways than std::enable_if to achieve the behavior that I want in the test code. However, the next simplified version of my use case, which itself requires std::enable_if .
#include <type_traits> #include <cassert> struct bar { using baz = int; }; template<class T> struct is_bar : std::false_type {}; template<> struct is_bar<bar> : std::true_type {}; template<class Bar> struct baz_type { using type = typename Bar::baz; }; template<class T> typename std::enable_if< std::is_integral< typename baz_type<T>::type >::value, int >::type foo(T x) { return 7; } template<class T> typename std::enable_if< !is_bar<T>::value, int >::type foo(T x) { return 13; } int main() { assert(foo(bar()) == 7); assert(foo(0) == 13); return 0; }
Compiler Output:
$ g++ --version ; echo ; g++ -std=c++11 repro.cpp g++ (Ubuntu 4.8.2-19ubuntu1) 4.8.2 Copyright (C) 2013 Free Software Foundation, Inc. This is free software; see the source for copying conditions. There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. repro.cpp: In instantiation of 'struct baz_type<int>': repro.cpp:29:3: required by substitution of 'template<class T> typename std::enable_if<std::is_integral<typename baz_type<Bar>::type>::value, int>::type foo(T) [with T = int]' repro.cpp:49:3: required from here repro.cpp:18:33: error: 'int' is not a class, struct, or union type using type = typename Bar::baz;
This code does not compile, because enable_if , used during the first foo overload, depends on the nested type T::baz . Since int does not have this nested type, the code is illegal.
What is the right way to express what I want?
source share