簡體   English   中英

用C ++編寫和檢查自己的概念

[英]Writing and checking your own concepts in c++

我正在編寫一個僅使用模板的僅標頭C ++庫。 現在,我想添加一些概念檢查,以處理在模板參數中使用錯誤類型時引發的編譯時錯誤。

例如,我需要可以指向單個對象的類指針對象(如std :: shared_ptr),可以指向數組(通過operator [])但不能與指針一起使用的類指針對象的概念算術(如std :: unique_ptr),以及可以與指針算術一起使用的指針,等等。

由於概念仍然不是標准的,編譯器也不支持,因此我需要自己實現。 我了解Boost Concept庫,但是由於某些原因,我不想將其添加到依賴項中。

所以問題是,如何實施某些類型要求的檢查? 如何在Boost中實施? 在這種情況下,通常使用哪些技術?

自從我一直在使用C ++ 11以來,我就自己做了一些此類事情。 本質上,這樣做的方法是大量使用SFINAE,並且對所有這些東西都非常熟悉: http : //en.cppreference.com/w/cpp/types

對於概念檢查而言,最重要的參數可以是enable_if :如果第一個模板參數為true ,那么它是一個提供給定返回類型的模板,如果該參數為false則將導致替換失敗:

//this one gets called only for pointers
template <typename T>
typename enable_if<is_pointer<T>::value, bool>::type do_stuff(T) {}

//this one gets called only for non-pointers
template <typename T>
typename enable_if<not is_pointer<T>::value, bool>::type do_stuff(T) {}

如果您不希望能夠重載此類內容並且喜歡可讀的錯誤消息,則應改用static_assert

template <typename T>
class pointer_thingy {
    static_assert(is_pointer<T>::value, "T must be a pointer");
    //...
};

現在,進入更困難的部分:定義自己的類似於概念的模板內容。 如果可能的話,最好的方法就是按照上面鏈接中已經存在的標准規范來編寫它們。 但是,有時您想檢查那里不可用的東西,例如特定操作的可用性。 在這種情況下,SFINAE是您的朋友:

template <typename T>
class is_equality_comparable {
    template <typename U> static auto check(const U& u) -> typename std::conditional<
            std::is_convertible<decltype(u == u), bool>::value,
            std::true_type, std::false_type>::type;
    static std::false_type check(...);
public:
    static constexpr bool value = decltype(check(std::declval<T>()))::value;
};

這將檢查特定類型是否定義了相等運算符( operator== ),以及是否返回可用作bool 但是,如何做到這一點值得一些解釋:此類的主要作用是定義一個永遠不會調用的check方法,並通過計算check的返回類型生成正確的值。 在底部,該類就是這樣做的:它使用假想類型T (通過declval生成以避免依賴於構造函數的值)調用時,確定check的返回類型。 為了使其正常工作,提供了兩個check重載:第一個重載為模板,第二個使用...表示法以接受任何參數,並具有比第一個重載更低的選擇優先級。 第一個重載使用后綴返回類型,以便它可以指它的參數(這使得代碼會更加清晰),並使用conditional之間進行選擇true_typefalse_type根據是否operator==正確地返回的東西可以作為一個bool 如果operator==不存在,則第一個重載將導致替換失敗,並且SFINAE確保將其從可能的重載列表中悄悄丟棄,這意味着假設的check調用將退回到第二個重載,該重載僅返回false_type

當然,這只是我的操作方式; 這是一種有效的方法,但是我不確定這是Boost的工作方式,還是其他人的工作方式。 如果您能夠使用具有實際概念支持的更新版本的C ++,則絕對應該使用它:在其他一些不錯的功能中,如果您做錯了某些事情,那么您將能夠獲得可理解的錯誤消息,這不一定是某些事情。您將擺脫上述方法。 最后要注意的是,如果您實際上決定做這樣的事情,那么嚴格的測試就至關重要:出錯很容易,而且當代碼中的其他地方已經使用了您的類時,很難弄清楚如何解決它。

暫無
暫無

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

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