简体   繁体   中英

SFINAE problems with std::begin

The following code works in Visual Studio 2013 but fails to compile with clang or gcc so I am guessing it is not valid c++.

#include <iterator>
#include <type_traits>
#include <vector>

template< typename T >
class SupportsStdBegin
{
  // std::false_type TestHasBegin( ... ) always exists.
  template< typename >
  static std::false_type TestSupportsBegin( ... );
  // std::true_type TestHasBegin( int ) only exists if std::begin( T() ) is a valid expression.
  template< typename U >
  static auto TestSupportsBegin( int ) -> decltype( std::begin( std::declval< T >() ), std::true_type{ } );

public:
  static const bool value = decltype( TestSupportsBegin< T >( 0 ) )::value;
};

static_assert( !SupportsStdBegin< int >::value, "'int' does not support std::begin()." );

const int TestArray[] = { 0, 1, 2, 3, 4, };
static_assert( SupportsStdBegin< decltype( TestArray ) >::value, "'const int TestArray[]' supports std::begin()." );

static_assert( SupportsStdBegin< std::vector< int > >::value, "'std::vector< int >' supports std::begin()." );

Can someone explain why SFINAE doesn't work as I'm expecting it to?

The line containing decltype( std::begin( std::declval< T >() ) fails for the static_assert for int type with the error:

error: no matching function for call to 'begin(int)'

I thought that this would mean SFINAE would fail and the implementation returning std::false_type would be used to set SupportsStdBegin< T >::value .

I understand there are alternate ways of writing this test but I would like to know why this particular way is not valid. I've successfully used it before to test if member functions exist.

For SFINAE to occur, the expression needs to be dependent on a template parameter in the immediate context of the template, ie the template parameter list.

The easy fix is to default U to T and use U in your dependent expression:

template <typename U=T>
static auto TestSupportsBegin( int ) 
    -> decltype( std::begin( std::declval< U >() ), std::true_type{ } );

Live Demo

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM