来自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>
。我认为这与在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); }
};
答案 0 :(得分:1)
答案在本节中:
/// 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
。
当针对给定模板实例化enum
中的check_base_dimension
时,它会查找采用这两种类型的boost_units_is_registered
函数。如果不存在这些模板参数的先前实例化,则会找到prevent_redefinition.hpp
中定义的函数,该函数返回detail::no
,但如果存在 ,则会找到函数的声明(friend
)匹配那些返回detail::yes
。
重要的是要注意这都是在编译时,而不是运行时。编译器用户argument-dependent lookup找到匹配的函数。 sizeof
该函数的结果仅取决于函数返回的内容 - 它根本不需要运行或调用,它只需要一个声明来给出返回值的大小。因此,当编译器找到friend
函数时,它可以确定sizeof
返回值然后 - 那里 - 函数实际上不需要定义。当然,如果您尝试使用它(如实际运行它),您将收到链接器错误,因为它已声明但从未定义过。
因此,sizeof()
在编译时确定为detail::yes
的大小,该大小与detail::no
的大小不同。因此,表达式的结果为false
,因此check_base_dimension::value
为false
,并且ordinal_has_already_been_defined
的实例化不会获得名为type
的成员变量。< / p>
编译器因此抛出一个错误,指出
detail::ordinal_has_already_been_defined<check_base_dimension<Derived, N>::value> does not have a member variable 'type'
或类似的。最后,实现了目标:您无法使用具有相同模板参数值的类的两个实例来编译代码。好哇!