[英]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.hpp
和prevent_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_dimension
的enum
時,它將查找采用這兩種類型的boost_units_is_registered
函數。 如果以前不存在這些模板參數的實例化,則它將找到prevent_redefinition.hpp
中定義的函數,該函數返回detail::no
,但如果確實存在,則找到與返回參數的參數相匹配的函數( friend
)的聲明。 detail::yes
。
重要的是要注意,所有這些都是在編譯時而不是運行時進行的。 編譯器用戶依賴於參數的查找以找到匹配的函數。 該sizeof
該函數的結果只取決於該函數返回的東西-它並不需要運行,或者叫可言,它只是需要一個聲明,讓返回值的大小。 因此,當編譯器找到friend
函數時,便可以確定返回值的sizeof
,該函數實際上不需要定義。 當然,如果您嘗試使用它(例如,使其實際運行),則會收到鏈接器錯誤,因為它已聲明但從未定義。
結果,在編譯時, sizeof()
被確定為detail::yes
的大小,這與detail::no
的大小不同。 因此,表達式的結果為false
,因此check_base_dimension::value
為false
,並且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.