2013-04-21 55 views
1

有誰知道如何用一個參數檢測構造函數?例如,這個結構應該有負面的結果:SFINAE - 用一個參數檢測構造函數

struct MyStruct 
{ 
    MyStruct(int x, int x2) : y(x) {} 
    int y; 
}; 

我這裏有一個很好的SFINAE檢查,看是否有類或結構與參數,以特定數量的構造函數。下面是一個爲3參數個數:

template <typename T> 
struct HasCtor3Args 
{ 
    struct Any { template <typename U> operator U(void); }; 

    template <typename U> 
    static int32 SFINAE(decltype(U(Any(), Any(), Any())) *); 

    template <typename U> 
    static int8 SFINAE(...); 

    static const bool value = sizeof(SFINAE<T>(NULL)) == sizeof(int32); 
}; 

這似乎工作得很好,因爲Any結構可以轉換成任何類型的參數應該是。然而問題是當試圖用一個參數檢測構造函數時。由於默認AnyT的類型相同,因此檢測到複製構造函數,SFINAE檢查似乎總是返回true。

編輯和更新: 我做了一些嘗試,但沒有似乎是一個走......這是最接近我可以得到,但不工作,因爲它總是返回true。當時的想法是,試圖得到拷貝構造函數來解決,而不是第一個「一網打盡」的呼叫:

template <typename T> 
struct HasCtor1Args 
{ 
    struct Any 
    { 
    template <typename U> 
    operator U() const; 
    }; 

    template <typename U> 
    static int32 SFINAE(decltype(U(Any())) *); 

    // Try to catch the copy ctor here 
    T MakeT(void); 
    template <typename U> 
    static int8 SFINAE(decltype(U(MakeT())) *); 

    template <typename U> 
    static int8 SFINAE(...); 

    static const bool value = sizeof(SFINAE<T>(NULL)) == sizeof(int32); 
}; 

我使用明確的關鍵字,隨着=刪除功能對於C++ 11也試過,然後意識到我需要使用的編譯器(微軟的)不允許這樣做。我也試過在轉換類型U上使用std :: enable_if,儘管我遇到了函數模板參數不能默認的錯誤。

+0

哦,還有['標準:: is_constructible'(HTTP:// EN .cppreference.com/w/cpp/types/is_constructible) – dyp 2013-04-22 00:23:33

+0

由於某些原因,它在轉換運算符是顯式的時候有效:'template 顯式運算符U()const;'。我不得不在標準版,但它可能是g ++ 4.8中的一個bug。 – dyp 2013-04-22 00:29:52

+0

嗯,我不認爲像這樣明確使用它可以在微軟的編譯器上工作, – RandyGaul 2013-04-22 00:37:02

回答

2

儘管n.m.的批評仍然存在,但這裏有一個版本來檢測一個類型只有一個 1參數非複製,非移動ctor。它使用SFINAE來限制Any的轉換。

注:與缺省參數附加構建函數會導致不確定性(如my_type(int, double=0);這是一個非常有限的解決方案

#include <cstdint> 
#include <type_traits> 

template <typename T> 
struct HasCtor1Args 
{ 
    struct Any 
    { 
     template 
     < 
     typename U, typename SFINAE = 
      typename std::enable_if< false == std::is_same<U,T>::value, U >::type 
     > 
     operator U() const; 
    }; 

    template <typename U> 
    static int32_t SFINAE(decltype(U(Any())) *); 

    template <typename U> 
    static int8_t SFINAE(...); 

    static const bool value = sizeof(SFINAE<T>(nullptr)) == sizeof(int32_t); 
}; 


struct my_type 
{ 
    my_type(int); 
    my_type(my_type const&); 
}; 

int main() 
{ 
    static_assert(HasCtor1Args<my_type> :: value, "epic fail"); 
} 
+0

Ooh,wait,nvm ...參數類型只會被推導爲「Any」,我想。默認參數也一樣。不過,它會失敗,因爲'template C(Something )'。 – Xeo 2013-04-22 16:53:31

+0

我不明白爲什麼它會失敗。 T只是成爲任何類型。 – 2013-04-22 16:54:30

+0

@Johannes:雅,看到我上面的新評論。 – Xeo 2013-04-22 16:54:54