[英]Using SFINAE to detect POD-ness of a type in C++
這里的原標題是VS2005 C++ 中 SFINAE 錯誤的解決方法
這是 SFINAE 的嘗試性使用,以生成 TR1 中存在的 is_pod 模板類的等效項(在 VS2005 中還沒有 TR1)。 當模板參數是 POD 類型(包括原始類型和由它們組成的結構)時,它的值成員應該是 true,否則它應該是 false(就像非平凡的構造函數一樣)。
template <typename T> class is_pod
{
public:
typedef char Yes;
typedef struct {char a[2];} No;
template <typename C> static Yes test(int)
{
union {T validPodType;} u;
}
template <typename C> static No test(...)
{
}
enum {value = (sizeof(test<T>(0)) == sizeof(Yes))};
};
class NonPOD
{
public:
NonPod(const NonPod &);
virtual ~NonPOD();
};
int main()
{
bool a = is_pod<char>::value;
bool b = is_pod<NonPOD>::value;
if (a)
printf("char is POD\n");
if (b)
printf("NonPOD is POD ?!?!?\n");
return 0;
}
問題是,不僅 VS 2005 沒有 TR1,它也不會關心上面的聯合(當模板參數不是 POD 時它應該無效),所以 a 和 b 評估為真。
感謝您在下面發布的答案。 仔細閱讀它們(和代碼)后,我意識到我試圖做的確實是一種錯誤的方法。 這個想法是將 SFINAE 行為與對模板must_be_pod的適應相結合(我在Imperfect C++一書中找到了它,但它也可以在其他地方找到)。 實際上,這將需要一套非常特殊的 SFINAE 規則,這顯然不是標准定義的。 畢竟,這並不是 VS 中的真正錯誤。
你的方法最大的問題是你不在這里做 SFINAE - SFINAE 只適用於參數類型和返回類型。
但是,在標准中的所有 SFINAE 情況中,沒有一個適用於您的情況。 他們是
這可能就是為什么在 Boost 文檔中,有:
如果沒有編譯器的一些(尚未指定的)幫助,ispod 永遠不會報告類或結構是 POD; 這總是安全的,如果可能是次優的。 目前(2005 年 5 月)只有 MWCW 9 和 Visual C++ 8 具有必要的編譯器-_intrinsics。
這也不適用於 VS2008,但我懷疑您也知道這一點。 SFINAE 用於為模板參數推導模板參數; 即使您可以創建與另一種類型不兼容的類型(即聯合不能使用非 POD),您也無法真正推斷出揭示類型構造函數的事物的類型。
事實上,VS 2008 使用編譯器對特征的支持來實現std::tr1::type_traits
。
我不確定你在這里嘗試做 SFINAE 的方式,因為is_pod<T>::test(...)
也會匹配is_pod<T>::test(0)
。 也許如果你使用不同的類型而不是 'int' 你會得到更好的匹配:
template <typename T> class is_pod
{
struct my_special_type { };
public:
typedef char Yes;
typedef struct {char a[2];} No;
template <typename C> static Yes test(my_special_type)
{
union {T validPodType;} u;
}
template <typename C> static No test(...)
{
}
enum {value = (sizeof(test<T>(my_special_type())) == sizeof(Yes))};
};
您可能還想查看Boost.Enable_if來為您執行 SFINAE —— 除非您正在嘗試實現自己的庫或出於某種原因。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.