2016-08-23 22 views
1

通常基於一類使用enable_if當模板類型,有必要複製類的模板類型作爲構造或方法的模板參數:當啓用基於它的構造函數時,是否總是需要複製類模板參數?

template < 
    typename U = T, 
    typename = typename std::enable_if< 
     !std::is_void<U>::value 
    >::type 
> 
Class() { } 

當恰好這是必要的(或不) ?

例如,下面的代碼編譯罰款G ++,鏘和VC++ ...

template <typename T = void> 
class Class { 
public: 
    template < 
     typename U, 
     typename = typename std::enable_if< 
      // Is the use of T here allowed? 
      std::is_void<T>::value 
      || std::is_base_of<T, U>::value 
     >::type 
    > 
    Class(U &&arg) { 
     std::cout << "Derived" << std::endl; 
    } 

    template < 
     typename U, 
     typename ...U_Rest, 
     typename = typename std::enable_if< 
      // Is the use of T here allowed? 
      !std::is_void<T>::value 
      && !std::is_base_of<T, U>::value 
     >::type 
    > 
    Class(U &&arg, U_Rest &&...rest) { 
     std::cout << "Not Derived" << std::endl; 
    } 
}; 

ideonerextester

...,而是直接使用T作爲enable_if的一部分。具體而言,如果Tvoid,則始終啓用構造函數的「派生」版本,並且始終禁用「未派生」版本,無論參數U如何。

以上實際是否按照標準合法?或者編譯器是否接受它,可能是由於「不需要診斷」?

回答

4

SFINAE適用於模板方法,它不應該是一個硬故障(所以主要應該取決於它的模板參數)。

這裏您的情況取決於U,所以它很好。

注意,你應該更喜歡

template <typename U, std::enable_if_t<cond>* = nullptr> 

template <typename U, typename = std::enable_if_t<cond>> 

允許寫殘疾人版本

template <typename U, std::enable_if_t<!cond>* = nullptr> 

template <typename U, typename = std::enable_if_t<cond>> //... 
template <typename U, typename = std::enable_if_t<!cond>> // ... 

具有相同的簽名。

+0

在我發佈的情況下,如果'T'爲'void',則條件不依賴於'U'。從你的回答中我收集到這將違法? – zennehoy

+0

關於風格的好處。我在這種情況下使用'typename = std :: enable_if_t'的原因是這個實現是在一個單獨的'.hpp'中,我不想複製'enable_if'條件。 – zennehoy

+0

@zennehoy:你有'true || std :: is_base_of :: value',你考慮短路,但第二個操作數可能會返回特殊類型,並且重載'operator ||'。所以這取決於。我會懷疑'真實|| sizeof(U)== 4',但我認爲它依賴於'U'的存在。 – Jarod42

相關問題