C++ 如果with is_枚举不起作用,则启用_

C++ 如果with is_枚举不起作用,则启用_,c++,c++11,sfinae,C++,C++11,Sfinae,MCVE: 为什么这不起作用?我该如何修复它 背景:这是一个尝试性的解决方案您看到的错误与自动类型推断有关,而不是如果和是枚举则启用 下面的工作 sfi.cc: In function 'int main()': sfi.cc:13:17: error: no matching function for call to 'func(Bar&, int)' func(bar, 1); ^ sfi.cc:13:17: note: candidat

MCVE:

为什么这不起作用?我该如何修复它


背景:这是一个尝试性的解决方案

您看到的错误与自动类型推断有关,而不是
如果
是枚举
则启用

下面的工作

sfi.cc: In function 'int main()':
sfi.cc:13:17: error: no matching function for call to 'func(Bar&, int)'
      func(bar, 1);
                 ^
sfi.cc:13:17: note: candidate is:
sfi.cc:4:10: note: template<class T> bool func(typename std::enable_if<std::is_e
num<_Tp>::value, T>::type&, int)
     bool func( typename std::enable_if< std::is_enum<T>::value, T >::type &t, int x )
          ^
sfi.cc:4:10: note:   template argument deduction/substitution failed:
sfi.cc:13:17: note:   couldn't deduce template parameter 'T'
      func(bar, 1);
                 ^
然后

现在
T
用于推导上下文。SFINAE仍会出现,但不会阻止模板类型推断

或者您可以等待C++1z概念,它可以自动执行上述构造(基本上)


看看这个链接的问题,解决问题的简单方法是标记分派

template<class T,class=typename std::enable_if< std::is_enum<T>::value >::type>
bool func( T &t, int x ) {
}
模板
布尔函数(T&T,int x)
{
//做些事情。。。
}
不过,我希望有三个不同的职能机构:

我们有3个案例:

  • 不是一个枚举

  • T是无符号字符

  • 其他一切

因此,调度:

template<typename T> 
bool func(T &t, int x)
{
    // do stuff...
}
名称空间详细信息{
模板
布尔函数(T&T,int x,std::true\u type/*是\u enum*/,std::false\u type){
}
模板
布尔函数(T&T,int x,std::false\u type,std::true\u type/*无符号字符*/){
}
模板
布尔函数(T&T,int x,std::false\u类型,std::false\u类型){
//都不是
}
}
模板
布尔函数(T&T,int x){
返回详细信息::func(t,x,std::is_enum{},std::is_same{});
}

现在使用常规重载规则在3个函数之间进行选择。如果您的类型同时是
enum
unsigned char
(不可能),则会出现编译时错误。

您正在非推断上下文中使用模板参数
T

从§14.8.2.5/5[临时扣减类型]

非推断上下文为:
-使用限定id指定的类型的嵌套名称说明符。
-

要解决此问题,请将
启用\u if
移动到虚拟模板参数

namespace details {
  template<class T>
  bool func( T& t, int x, std::true_type /* is_enum */, std::false_type ) {
  }
  template<class T>
  bool func( T& t, int x, std::false_type, std::true_type /* unsigned char */ ) {
  }
  template<class T>
  bool func( T& t, int x, std::false_type, std::false_type ) {
    // neither
  }
}
template<class T>
bool func( T& t, int x ) {
  return details::func( t, x, std::is_enum<T>{}, std::is_same<unsigned char, T>{} );
}
template<typename T,
         typename = typename std::enable_if< std::is_enum<T>::value, T >::type>
bool func( T &t, int x )
{
  // ...
}
或者在返回类型中使用
enable\u if
表达式

template<typename T,
         typename std::enable_if< std::is_enum<T>::value, int >::type* = nullptr>
bool func( T &t, int x )
{
  // ...
}
模板
typename std::enable_如果::type
函数(T&T,int x)
{
// ...
}

好的,这很重要。它似乎也适用于包装器:
template bool func2(T&T,int x){return func(T,x);}
Right,我在尝试您的第一个建议时确实遇到了多个定义错误,无法理解它们出现的原因,因此也感谢您的解释:)
template<class T>
bool func( typename blah<T>::type );
template<class T,class=typename std::enable_if< std::is_enum<T>::value >::type>
bool func( T &t, int x ) {
}
template<typename T> 
bool func(T &t, int x)
{
    // do stuff...
}
namespace details {
  template<class T>
  bool func( T& t, int x, std::true_type /* is_enum */, std::false_type ) {
  }
  template<class T>
  bool func( T& t, int x, std::false_type, std::true_type /* unsigned char */ ) {
  }
  template<class T>
  bool func( T& t, int x, std::false_type, std::false_type ) {
    // neither
  }
}
template<class T>
bool func( T& t, int x ) {
  return details::func( t, x, std::is_enum<T>{}, std::is_same<unsigned char, T>{} );
}
template<typename T,
         typename = typename std::enable_if< std::is_enum<T>::value, T >::type>
bool func( T &t, int x )
{
  // ...
}
template<typename T,
         typename std::enable_if< std::is_enum<T>::value, int >::type* = nullptr>
bool func( T &t, int x )
{
  // ...
}
template<typename T>
typename std::enable_if< std::is_enum<T>::value, bool >::type 
    func( T &t, int x )
{
    // ...
}