1

来自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.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); }
};
4

1 回答 1

1

啊哈,我相信我拥有它。

答案在本节:

        /// 注册这个序数
        /// 仅限内部
        朋友详细信息::是的
        boost_units_is_registered(常量单位::base_dimension_ordinal&)
        {返回(详细信息::是());}

        /// 但要确保我们可以识别当前的实例化!
        /// 仅限内部
        朋友详细信息::是的
        boost_units_is_registered(常量单位::base_dimension_pair&)
        {返回(详细信息::是());}

friend声明表明存在与这些参数匹配的函数,并返回detail::yes.

当为给定模板实例化enumin时,它会查找采用这两种类型的函数。如果这些模板参数的先前实例不存在,它会找到返回 a的函数,但如果确实存在,它会找到与返回.check_base_dimensionboost_units_is_registeredprevent_redefinition.hppdetail::nofrienddetail::yes

重要的是要注意这都是在编译时,而不是运行时。编译器使用依赖于参数的查找来查找匹配的函数。该sizeof函数的结果仅取决于函数返回的内容——它根本不需要运行或调用,它只需要一个给出返回值大小的声明。因此,当编译器找到friend函数时,它就可以确定sizeof返回值——函数实际上不需要有定义。当然,如果您尝试使用它(例如,让它实际运行),您会收到链接器错误,因为它已声明但从未定义。

结果,sizeof()在编译时确定 a 的大小与 adetail::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'

或类似的。最终,目标达到了:你不能用两个具有相同模板参数值的类实例来编译代码。嘘!

于 2012-08-02T23:40:03.363 回答