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

1 に答える 1

1

ああ、私はそれを持っていると信じています。

答えはこのセクションにあります:

        ///この序数を登録します
        ///内部のみ
        友達の詳細::はい
        boost_units_is_registered(const units :: base_dimension_ordinal&)
        {return(detail :: yes()); }

        ///ただし、現在のインスタンス化を識別できることを確認してください。
        ///内部のみ
        友達の詳細::はい
        boost_units_is_registered(const units :: base_dimension_pair&)
        {return(detail :: yes()); }

宣言は、これらfriendの引数に一致する関数が存在することを示し、を返しますdetail::yes

enumincheck_base_dimensionが特定のテンプレートに対してインスタンス化されると、これらboost_units_is_registered2つのタイプをとる関数を探します。これらのテンプレートパラメータの以前のインスタンス化が存在しない場合は、で定義された関数を検出しますが、存在する場合prevent_redefinition.hpp、を返す引数に一致する関数()の宣言を検出します。detail::nofrienddetail::yes

これはすべて実行時ではなく、コンパイル時に行われることに注意することが重要です。コンパイラーは、引数に依存するルックアップを使用して、一致する関数を見つけます。そのsizeof関数の結果は、関数が返すものにのみ依存します。実行したり呼び出したりする必要はまったくなく、戻り値のサイズを示す宣言が必要なだけです。したがって、コンパイラが関数を見つけると、戻り値をその場でfriend決定できます。関数に実際に定義を付ける必要はありません。sizeofもちろん、これを使用しようとすると(たとえば、実際に実行してもらうと)、宣言されているが定義されていないため、リンカーエラーが発生します。

その結果、sizeof()コンパイル時に、はaのサイズdetail::yesとは異なるaのサイズであると判断されますdetail::no。したがって、式の結果は、falseであり、したがって、であり、のインスタンス化check_base_dimension::valueは、と呼ばれるメンバー変数を取得しません。falseordinal_has_already_been_definedtype

したがって、コンパイラは次のことを示すエラーをスローします。

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

または類似。最終的に、目標は達成されます。同じテンプレートパラメータ値を持つクラスの2つのインスタンスでコードをコンパイルすることはできません。ハザ!

于 2012-08-02T23:40:03.363 に答える