簡體   English   中英

使用CRTP技術確保唯一的模板參數

[英]Using CRTP technique to ensure unique template arguments

boost::units

struct my_base_dimension1 : units::base_dimension<my_base_dimension1, 1> { };  // ok
struct my_base_dimension2 : units::base_dimension<my_base_dimension2, 2> { };  // ok
struct my_base_dimension3 : units::base_dimension<my_base_dimension3, 2> { };  // error

我試圖了解代碼如何確保模板參數唯一。 我不明白check_base_dimension如何最終返回非零值,這會觸發ordinal_has_already_been_defined<true> 我認為這與在base_dimension中重新定義的boost_units_is_registered() base_dimension ,但是我不知道如何調用friend版本。 有任何想法嗎?

有問題的文件是base_dimension.hppprevent_redefinition.hpp

template<class Derived, long N,
         class = typename detail::ordinal_has_already_been_defined<
             check_base_dimension<Derived, N>::value
             >::type
         >
class base_dimension : public ordinal<N>
{
public:
    typedef base_dimension this_type;
    typedef list<dim<Derived,static_rational<1> >, dimensionless_type> dimension_type;
    typedef Derived type;

private:                                                                                                                           
    friend Derived*
    check_double_register(const units::base_dimension_ordinal<N>&)
        { return(0); }

    friend detail::yes
    boost_units_is_registered(const units::base_dimension_ordinal<N>&)
        { detail::yes result; return(result); }

    friend detail::yes
    boost_units_is_registered(const units::base_dimension_pair<Derived, N>&)
        { detail::yes result; return(result); }
};

啊哈,我相信我有。

答案在本節中:

/// Register this ordinal
        /// INTERNAL ONLY
        friend detail::yes 
        boost_units_is_registered(const units::base_dimension_ordinal&) 
        { return(detail::yes()); }

        /// But make sure we can identify the current instantiation!
        /// INTERNAL ONLY
        friend detail::yes 
        boost_units_is_registered(const units::base_dimension_pair&) 
        { return(detail::yes()); }

friend聲明表明存在與那些參數匹配的函數,並返回detail::yes

當為給定的模板實例化check_base_dimensionenum時,它將查找采用這兩種類型的boost_units_is_registered函數。 如果以前不存在這些模板參數的實例化,則它將找到prevent_redefinition.hpp中定義的函數,該函數返回detail::no ,但如果確實存在,則找到與返回參數的參數相匹配的函數( friend )的聲明。 detail::yes

重要的是要注意,所有這些都是在編譯時而不是運行時進行的。 編譯器用戶依賴參數的查找以找到匹配的函數。 sizeof該函數的結果只取決於該函數返回的東西-它並不需要運行,或者叫可言,它只是需要一個聲明,讓返回值的大小。 因此,當編譯器找到friend函數時,便可以確定返回值的sizeof ,該函數實際上不需要定義。 當然,如果您嘗試使用它(例如,使其實際運行),則會收到鏈接器錯誤,因為它已聲明但從未定義。

結果,在編譯時, sizeof()被確定為detail::yes的大小,這與detail::no的大小不同。 因此,表達式的結果為false ,因此check_base_dimension::valuefalse ,並且ordinal_has_already_been_defined的實例化未獲得名為type的成員變量。

因此,編譯器將引發錯誤,指出

detail::ordinal_has_already_been_defined<check_base_dimension<Derived, N>::value> does not have a member variable 'type'

或類似。 最后,目標得以實現:您無法使用具有相同模板參數值的類的兩個實例來編譯代碼。 暈!

暫無
暫無

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

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