C++ 如果似乎在类外但在类内不起作用,则启用

C++ 如果似乎在类外但在类内不起作用,则启用,c++,templates,c++11,sfinae,C++,Templates,C++11,Sfinae,这是我有点奇怪的代码: 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&>
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) {}  
模板
A类{
公众:
void b(typename std::enable_if::value,T>;::type o){}
void b(typename std::enable_if;::type o){
};  
模板
void b(typename std::enable_if::value,T>::type o){}
模板
void b(typename std::enable_if::type o){}
如果我
ifdef
退出方法
b
并调用
b(pi
),其中
pi
int*
,则所有内容都将编译

如果我
ifdef
退出函数
b
(课外)并调用
A;a、 b(pi)
,我得到以下错误:

错误:std::\uu 1::如果启用,则没有名为“type”的类型。


为什么会出现不一致的情况?我如何解决这个问题,以便在一个特定的环境中使用这些方法

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

在实例化时,方法签名如下所示(不管调用它们):

void A::b(std::enable_if::type o)//错误
无效A::b(std::enable_if::type o)
要解决此问题,请同时制作方法模板:

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
};
模板
甲级{
公众:
模板
void b(uo,typename std::enable_if::value>::type*=0){}
//其他版本也一样
};
另一方面,使用SFINAE的更好方法是推导模板参数,因此您应该修改自由函数,使其如下所示:

template<class T>
void b(T o, typename std::enable_if<!std::is_pointer<T>::value>::type* = 0){}
// same for the other version
模板
void b(to,typename std::enable_if::value>::type*=0){}
//其他版本也一样
在C++11中,您甚至可以使用SFINAE的模板参数:

template<class T, EnableIf<std::is_pointer<T>> = {}>
void b(T o);
模板
无效b(to);
使用以下链接的博客条目中的别名:

命名空间详细信息{enum class enabler{};}
模板
使用EnableIf=typename std::enable_if::type;

您没有正确使用SFINAE,因为编译器无法推断
enable_if::type
的参数,这可能就是它失败的原因

独立功能的正确声明应为:

template <typename T>  
typename std::enable_if<!std::is_pointer<T>::value, void>::type b(T o);

template <typename T>  
typename std::enable_if<std::is_pointer<T>::value, void>::type b(T o);
模板
typename std::enable_if::value,void>::类型b(to);
模板
typename std::enable_if::type b(to);
在这种特殊情况下,也可以使用普通函数重载:

template <typename T>  
void b(T);

template <typename T>  
void b(T*);
模板
无效b(T);
模板
无效b(T*);

有关解释,请参阅Xeo的答案

解决方法:只需向方法添加一个伪模板参数

#include <utility>
#include <type_traits>

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

  template <typename U = T>
  void b(typename std::enable_if<std::is_pointer<U>::value, U>::type o);
};

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

template <typename T>  
template <typename U>
void A<T>::b(typename std::enable_if<std::is_pointer<U>::value, U>::type o) {} 


int main() {
    A<int> a;
    a.b(0);
}
#包括
#包括
模板
A类{
公众:
模板
void b(typename std::enable_if::value,U>::type o);
模板
void b(typename std::enable_if::type o);
};
模板
模板
void A::b(typename std::enable_if::value,U>::type o){}
模板
模板
void A::b(typename std::enable_if::type o){
int main(){
A A;
a、 b(0);
}

.

什么?如果成员方法本身是模板,那么像OP那样使用
enable_是完全可以的。最好解释如何通过添加伪模板参数来“转换”方法,以重新激活这些方法上的SFINAE。这没有帮助,方法签名是固定的,替换发生在
A
的实例化点。另外,免费函数看起来也不太正确P@Xeo:这些不是自由函数,而是方法的定义(以说明不应重复默认值)。不管怎样,我把它补好了。
template <typename T>  
void b(T);

template <typename T>  
void b(T*);
#include <utility>
#include <type_traits>

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

  template <typename U = T>
  void b(typename std::enable_if<std::is_pointer<U>::value, U>::type o);
};

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

template <typename T>  
template <typename U>
void A<T>::b(typename std::enable_if<std::is_pointer<U>::value, U>::type o) {} 


int main() {
    A<int> a;
    a.b(0);
}