亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

請問只接受某些類型的C+模板

請問只接受某些類型的C+模板

C++
臨摹微笑 2019-08-02 03:02:26
只接受某些類型的C+模板在Java中,您可以定義只接受擴展您選擇的類型的泛型類,例如:public class ObservableList<T extends List> {   ...}這是使用“擴展”關鍵字完成的。在C+中是否有一些簡單的等價關鍵字?
查看完整描述

3 回答

?
開滿天機

TA貢獻1786條經驗 獲得超13個贊

我建議用Boost‘s靜態斷言is_base_of在Boost Type特性庫中:

template<typename T>class ObservableList {
    BOOST_STATIC_ASSERT((is_base_of<List, T>::value)); //Yes, the double parentheses are needed, otherwise the comma will be seen as macro argument separator
    ...};

在其他一些更簡單的情況下,您可以簡單地轉發-聲明一個全局模板,但只為有效類型定義(顯式或部分專門化)它:

template<typename T> class my_template;     // Declare, but don't define// int is a valid typetemplate<> class my_template<int> {
    ...};// All pointer types are validtemplate<typename T> class my_template<T*> {
    ...};// All other types are invalid, and will cause linker error messages.




查看完整回答
反對 回復 2019-08-03
?
達令說

TA貢獻1821條經驗 獲得超6個贊

這在C+中通常是沒有道理的,正如這里的其他答案所指出的那樣。在C+中,我們傾向于基于“從該類繼承”以外的其他約束來定義泛型類型。如果你真的想這么做,在C+11和<type_traits>:

#include <type_traits>template<typename T>class observable_list {
    static_assert(std::is_base_of<list, T>::value, "T must inherit from list");
    // code here..};

不過,這打破了人們在C+中所期望的許多概念。最好是用一些技巧,比如定義你自己的特質。例如,也許observable_list希望接受任何具有類型防御的容器。const_iterator和一個beginend返回的成員函數const_iterator..如果將此限制為從list然后,擁有自己類型的用戶不會繼承list但是提供這些成員函數,并且類型設置將無法使用observable_list.

這個問題有兩種解決方案,一種是不限制任何東西,并依賴鴨子類型。這個解決方案的一個大缺點是,它涉及到大量的錯誤,用戶很難去摸索。另一種解決方案是定義特征,以約束為滿足接口需求而提供的類型。這個解決方案的最大缺點是涉及額外的寫作,這可以被看作是煩人的。然而,積極的一面是,您將能夠編寫自己的錯誤消息a la。static_assert.

為了完整起見,給出了上述示例的解決方案:

#include <type_traits>template<typename...>struct void_ {
    using type = void;};template<typename... Args>using Void = typename void_<Args...>::type;template<typename T, typename = void>struct has_const_iterator : std::false_type {};template<typename T>struct has_const_iterator<T, Void<typename T::const_iterator>> : std::true_type {};struct has_begin_end_impl {
    template<typename T, typename Begin = decltype(std::declval<const T&>().begin()),
                         typename End   = decltype(std::declval<const T&>().end())>
    static std::true_type test(int);
    template<typename...>
    static std::false_type test(...);};template<typename T>struct has_begin_end : decltype(has_begin_end_impl::test<T>(0)) {};template<typename T>class observable_list {
    static_assert(has_const_iterator<T>::value, "Must have a const_iterator typedef");
    static_assert(has_begin_end<T>::value, "Must have begin and end member functions");
    // code here...};

在上面的示例中,有許多概念展示了C+11的特性。對好奇者的一些搜索術語是各種模板、SFINAE、表達式SFINAE和類型特征。




查看完整回答
反對 回復 2019-08-03
?
倚天杖

TA貢獻1828條經驗 獲得超3個贊

目前還沒有人提到的簡單解決辦法就是忽略這個問題。如果我試圖使用int作為函數模板中需要容器類(如向量或列表)中的模板類型,我將得到一個編譯錯誤。粗糙而簡單,但它解決了問題。編譯器將嘗試使用您指定的類型,如果失敗,它將生成編譯錯誤。

唯一的問題是,您得到的錯誤消息將是棘手的閱讀。然而,這是一種非常普遍的做法。標準庫中滿是函數或類模板,這些模板期望模板類型的某些行為,并且不做任何檢查所使用的類型是否有效的操作。

如果您想要更好的錯誤消息(或者如果您想捕獲不會產生編譯器錯誤但仍然沒有意義的情況),可以使用Boost的靜態斷言或Boost概念_CHECK庫,這取決于您想要的復雜程度。

使用最新的編譯器,您有一個內置的static_assert,可以用來代替。




查看完整回答
反對 回復 2019-08-03
  • 3 回答
  • 0 關注
  • 432 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號