Another question about the type "who is right between g ++ and clang ++?" for standard C ++ gurus.
Suppose we want to apply SFINAE to a variable template to include this variable only if the template type satisfies a certain condition.
For example: enable barif (and only if) the type of the template has a method foo()with a given signature.
Using SFINAE through an optional template type with default value
template <typename T, typename = decltype(T::foo())>
static constexpr int bar = 1;
works for both g ++ and clang ++, but has a problem: it can be hacked explaining the second type of template
So
int i = bar<int>;
gives a compilation error where
int i = bar<int, void>;
compile without problems.
So, due to my ignorance of SFINAE, I tried to enable / disable the type of the same variable:
template <typename T>
static constexpr decltype(T::foo(), int{}) bar = 2;
: () g++, clang++
tmp_003-14,gcc,clang.cpp:8:30: error: no member named 'foo' in 'without_foo'
static constexpr decltype(T::foo(), int{}) bar = 2;
~~~^
, , : ? g++ clang++?
: ++ 14, SFINAE ?
#include <type_traits>
template <typename T>
static constexpr decltype(T::foo(), int{}) bar = 2;
struct with_foo
{ static constexpr int foo () { return 0; } };
struct without_foo
{ };
template <typename T>
constexpr auto exist_bar_helper (int) -> decltype(bar<T>, std::true_type{});
template <typename T>
constexpr std::false_type exist_bar_helper (...);
template <typename T>
constexpr auto exist_bar ()
{ return decltype(exist_bar_helper<T>(0)){}; }
int main ()
{
static_assert( true == exist_bar<with_foo>(), "!" );
static_assert( false == exist_bar<without_foo>(), "!" );
}