enable_if似乎在一个类之外但不在内部

Fre*_*kle 4 c++ templates sfinae c++11

这是我有点奇怪的代码:

template <typename T&>
class A {  
public:  
  void b(typename std::enable_if<!std::is_pointer<T>::value, T>;::type o) {}  
  void b(typename std::enable_if<std::is_pointer<T>::value, T>;::type o) {}  
};  

template <typename T>  
void b(typename std::enable_if<!std::is_pointer<T>::value, T>::type o) {}  
template <typename T>  
void b(typename std::enable_if<std::is_pointer<T>::value, T>::type o) {}  
Run Code Online (Sandbox Code Playgroud)

如果我ifdef出了方法b和呼叫b<int *>(pi),其中piint *,一切编译.

如果我ifdef退出函数b(外部类)并调用A<int *> a; a.b(pi),我会收到以下错误:

error: no type named 'type' in 'std::__1::enable_if<false, int *>'

为什么不一致以及如何解决问题以便我可以使用A中的方法?

Xeo*_*Xeo 9

问题是,SFINAE仅在重载解析期间起作用,并且仅在函数本身是模板时才起作用.在您的方法案例中,整个是一个模板,这意味着没有替换模板参数(请记住:SFINAE ==" 替换失败不是错误").

在实例化时,方法签名看起来像这样(永远不要调用它们):

void A<int*>::b(std::enable_if<false, int*>::type o) // error
void A<int*>::b(std::enable_if<true, int*>::type o)
Run Code Online (Sandbox Code Playgroud)

要解决此问题,请创建方法模板:

template<class T>
class A{
public:
  template<class U>
  void b(U o, typename std::enable_if<!std::is_pointer<U>::value>::type* = 0){}
  // same for the other version
};
Run Code Online (Sandbox Code Playgroud)

另外,让模板参数推断是使用SFINAE的更好方法,因此您应该将自由函数修改为如下所示:

template<class T>
void b(T o, typename std::enable_if<!std::is_pointer<T>::value>::type* = 0){}
// same for the other version
Run Code Online (Sandbox Code Playgroud)

在C++ 11中,您甚至可以使用SFINAE的模板参数:

template<class T, EnableIf<std::is_pointer<T>> = {}>
void b(T o);
Run Code Online (Sandbox Code Playgroud)

利用此处链接的博客条目中的别名:

namespace detail{ enum class enabler{}; }

template<class Cond, class T = detail::enabler>
using EnableIf = typename std::enable_if<C::value, T>::type;
Run Code Online (Sandbox Code Playgroud)