簡體   English   中英

enable_if似乎在一個類之外但不在內部

[英]enable_if seems to work outside a class but not inside

這是我有點奇怪的代碼:

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) {}  

如果我ifdef該方法b和呼叫b<int *>(pi ),其中piint * ,一切編譯。

如果我ifdef函數b (外部類)並調用A<int *> a; ab(pi) A<int *> a; ab(pi) ,我收到以下錯誤:

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

為什么不一致以及如何解決問題以便我可以使用A中的方法?

問題是,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)

要解決此問題,請創建方法模板:

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
};

另外,讓模板參數推斷是使用SFINAE的更好方法,因此您應該將自由函數修改為如下所示:

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

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

template<class T, EnableIf<std::is_pointer<T>> = {}>
void b(T o);

利用此處鏈接的博客條目中的別名:

namespace detail{ enum class enabler{}; }

template<class Cond, class T = detail::enabler>
using EnableIf = typename std::enable_if<C::value, T>::type;

有關解釋,請參閱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);
}

現場演示

您沒有正確使用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);

在這種特殊情況下,也可以使用普通函數重載:

template <typename T>  
void b(T);

template <typename T>  
void b(T*);

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM