簡體   English   中英

使用 SFINAE 檢測 C++ 中類型的 POD-ness

[英]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 情況中,沒有一個適用於您的情況。 他們是

  • void、引用、函數或無效大小的數組
  • 不是類型的類型成員
  • 指向引用的指針、對引用的引用、對 void 的引用
  • 指向非類類型成員的指針
  • 模板值參數的無效轉換
  • 參數類型為 void 的函數類型
  • const/volatile 函數類型

這可能就是為什么在 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.

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