【问题标题】:Substitution failure is sometimes an error?替换失败有时是错误?
【发布时间】:2012-12-28 17:13:24
【问题描述】:

以下代码片段尝试实现一个 'std::is_constructible':

#include <type_traits>

struct A { 
  // A(int);
};

template< typename T >
struct cstr_int
{
  static int mi;

  template< typename C >
  static typename std::enable_if< 
    std::is_same< decltype( T( mi ) ), T >::value, char >::type choose( C * );
  static long choose( ... );

  enum { value = ( sizeof( decltype( choose( & mi ) ) ) == 1 ) };
};

bool const b1 = cstr_int< A >::value;

使用 g++ 可以正常工作;使用 clang++ 会打印以下错误:

tmp/sfinae04.cc:14:29: error: no matching conversion for functional-style cast from 'int' to 'A'
    std::is_same< decltype( T( mi ) ), T >::value, char >::type choose( C * );
                            ^~~~~
tmp/sfinae04.cc:20:17: note: in instantiation of template class 'cstr_int<A>' requested here
bool const b1 = cstr_int< A >::value;
                ^
tmp/sfinae04.cc:3:8: note: candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const A' for 1st argument
struct A { 
       ^
tmp/sfinae04.cc:3:8: note: candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'A' for 1st argument
struct A { 
       ^
tmp/sfinae04.cc:3:8: note: candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided
1 error generated.

版本信息:clang 版本 3.3 (trunk 172418) (llvm/trunk 172417), g++ (Debian 4.7.2-4) 4.7.2。

我的问题: 恕我直言,这应该是 SFINAE。我在这里错过了什么还是clang++有问题?

(我知道有 is_constructible() 但我不允许使用它 - 这不是我的问题的重点。)

【问题讨论】:

  • 我认为问题在于您在enable_if 中使用了 T 而不是 C。没有替换失败,因为 T=A 是已知的。
  • 是的 - 你是对的:这也正是 Bart van Ingen Schenau 在他的回答中提到的。谢谢。

标签: c++ sfinae clang++


【解决方案1】:

虽然在您看来它可能是替换失败,但它实际上是在模板实例化期间检测到的失败,因此是可诊断的错误。

不是 SFINAE 上下文,因为enable_if 不依赖于推导的模板参数。

这行得通:

template< typename T >
struct cstr_int
{
  static int mi;

  template< typename C >
  static typename std::enable_if< 
    std::is_same< decltype( C( mi ) ), C >::value, char >::type choose( C * );
  static long choose( ... );

  enum { value = ( sizeof( decltype( choose( (T*)0 ) ) ) == 1 ) };
};

【讨论】:

    猜你喜欢
    • 2013-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-27
    • 2013-12-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多