简体   繁体   English

SFINAE与std :: begin的问题

[英]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++. 以下代码适用于Visual Studio 2013,但无法使用clang或gcc进行编译,因此我猜测它不是有效的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? 有人可以解释为什么SFINAE不能像我期望的那样工作吗?

The line containing decltype( std::begin( std::declval< T >() ) fails for the static_assert for int type with the error: 包含decltype( std::begin( std::declval< T >() )的行对于int类型的static_assert失败,并带有错误:

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 . 我认为这意味着SFINAE会失败,返回std::false_type的实现将用于设置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. 为了发生SFINAE,表达式需要依赖于模板的直接上下文中的模板参数,即模板参数列表。

The easy fix is to default U to T and use U in your dependent expression: 简单的修复是默认UT并在您的依赖表达式中使用U

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

Live Demo 现场演示

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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