簡體   English   中英

SFINAE具有升壓啟用,如果

[英]SFINAE with boost enable if

我正在嘗試實現一個使用sfinae區分數組和非數組類型的模板對類。 到目前為止,我有以下代碼:

template <typename T>
class pair
{
public:

   //default constructors. one for non-array types and one for arrays. These work.
   template <typename temp_type = T>
   pair(typename boost::disable_if<boost::is_array<temp_type>>::type* ignore = 0)
      : first(T())
      , second(T())
   {}

   template <typename temp_type = T>
   pair(typename boost::enable_if<boost::is_array<temp_type>>::type* ignore = 0)
   {}

   //assignment operator attempts for non-array types (not in code at same time.) These don't work.
   template<typename temp_type = T> 
   pair<temp_type>& operator=(pair<typename boost::disable_if<boost::is_array<temp_type>>::type>                const& rhs)
   {
       this->first = rhs.first;
       this->second = rhs.second;
       return *this;
   }

   template<typename temp_type = T> 
   auto operator=(pair<temp_type> const& rhs) -> pair<typename boost::disable_if<boost::is_array<temp_type>>::type>&
   {
       this->first = rhs.first;
       this->second = rhs.second;
       return *this;
   }

   T first;
   T second;
};

賦值運算符的首次嘗試失敗,並出現“非法使用void類型”錯誤。 第二個編譯,但是當我調試時,MSVC告訴我“該行沒有關聯的可執行代碼”。 我正在使用MSVC 12 64位編譯器。

如果您可以提供有關此處錯誤之處的任何見解,那將非常有幫助。

另外,我對C ++中的sfinae所做的一些觀察(可能是對還是錯):

  • sfinae要求對成員函數進行模板化,但不能為此目的使用類模板類型。 為什么?
  • 只能通過修改模板參數而不是返回類型或輸入來完成sfinae。 究竟如何運作? 這種方法的靈活性是什么?

我知道這很漫長,並且在許多其他文章中都涉及了參考主題,但是我無法以一種簡潔地解釋c ++ sfinae的方式將這些解釋放在一起。

我讀過的一些文章:

向非C ++程序員解釋C ++ SFINAE (高級介紹)

使用enable_if選擇類構造函數 (構造函數為sfinae)

謝謝你的幫助。

編輯:

我已經根據以下注釋修改了我的代碼,但仍然無法按預期工作(編譯器甚至沒有看到源代碼。)這是一種有趣的情況,因為該示例完全是人為設計的,並且默認賦值運算符實際上可以工作在這種情況下。 不過,我認為編譯器不應取代我重載運算符的嘗試。

我嘗試了以下4種方法,但似乎沒有一個內置於可執行文件中:

template<typename temp_type = T> 
pair<temp_type>& operator=(pair<typename boost::disable_if<boost::is_array<temp_type>, temp_type>::type> const& rhs)

{
        this->first = rhs.first;
        this->second = rhs.second;
        return *this;
}

template<typename temp_type = T>
auto operator=(pair<temp_type> const& rhs) -> pair<typename boost::disable_if<boost::is_array<temp_type>, temp_type>::type>&
{
    this->first = rhs.first;
    this->second = rhs.second;
    return *this;
}

template<typename ret_type = boost::disable_if<boost::is_array<T>, T>::type, typename = void>
pair<ret_type>& operator=(pair<ret_type> const& rhs)
{
    this->first = rhs.first;
    this->second = rhs.second;
    return *this;
}

template<typename temp_type = T, typename boost::enable_if<boost::is_array<temp_type>, temp_type>::type = 0>
pair<T>& operator=(pair<temp_type> const& rhs)
{
    this->first = rhs.first;
    this->second = rhs.second;
    return *this;
}

思考?

別忘了,轉換分配可以通過模板函數來實現,但是復制和移動分配操作符則不能。

用戶聲明的副本分配運算符X::operator=是類X一個非靜態非模板成員函數,具有恰好一個參數,類型為XX&const X&volatile X&const volatile X&

如果類定義沒有顯式聲明一個副本分配運算符,則隱式聲明一個。 如果類定義聲明了move構造函數或move賦值運算符,則隱式聲明的副本賦值運算符將定義為Delete; 否則,它定義為默認值

用戶聲明的移動分配運算符X::operator=是類X一個非靜態非模板成員函數,具有一個類型為X&&const X&&volatile X&&const volatile X&&

和筆記

因為模板賦值運算符或采用右值參考參數的賦值運算符永遠都不是副本賦值運算符,所以這種賦值運算符的存在不會抑制副本賦值運算符的隱式聲明。 這樣的賦值運算符將與其他賦值運算符(包括副本賦值運算符)一起參與重載解析,並且,如果選中該賦值符,則將用於分配對象。

(在第12.8節中找到引號,n3936草案的措詞)

@BenVoigt的答案解釋了為什么您的嘗試失敗的原因 ,這里僅是替代解決方案。 您可以根據實例化模板的類型,將operator=調用分派到適當的重載:

#include <iostream>
#include <boost/type_traits.hpp>

template <typename T>
class pair
{    
public:    
    pair& operator=(pair const& rhs)
    {
        return assign(rhs, boost::is_array<T>());
    }

private:
    pair& assign(pair const&, boost::true_type)
    {
        std::cout << "array" << std::endl;
        return *this;
    }

    pair& assign(pair const&, boost::false_type)
    {
        std::cout << "not array" << std::endl;
        return *this;
    }
};

int main()
{
    pair<int> a, b;
    b = a;

    pair<int[]> c, d;
    c = d;
}

輸出:

not array
array

您可以對構造函數執行相同的操作,將調用委派給另一個(C ++ 11):

pair() : pair(boost::is_array<T>()) {}

pair(boost::true_type) { /*initialize array pair*/ }

pair(boost::false_type) { /*initialize non-array pair*/ }

代碼看起來更簡潔,您不必與operator=更好地匹配實際參數的編譯器競爭。

DEMO

暫無
暫無

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

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