4

実際、インテル®コンパイラーを使用してライブラリーをコンパイルする際に問題が発生しました。

この同じライブラリは、g++で適切にコンパイルされています。

テンプレートが原因で問題が発生します。私が理解したいのは、 **typename**テンプレートではない関数パラメーターとしての宣言と、関数本体内の変数宣言です。

例:

void func(typename sometype){..
...
typename some_other_type;
..
}

この種のコードをコンパイルすると、次のエラーが発生します(intel)、(gccは主張しません):次のエラーがあります

../../../libs/log/src/attribute_set.cpp(415): error: no operator "!=" matches these operands
            operand types are: boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'> != boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'>
      while (begin != end)
                   ^
          detected during instantiation of "void boost::log_st::basic_attribute_set<CharT>::erase(boost::log_st::basic_attribute_set<CharT>::iter<'\000'>, boost::log_st::basic_attribute_set<CharT>::iter<'\000'>) [with CharT=wchar_t]" at line 438

../../../boost/log/attributes/attribute_set.hpp(115): error: no operator "!=" matches these operands
            operand types are: boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'> != boost::log_st::basic_attribute_set<wchar_t>::iter<'\000'>
              if (it != m_pContainer->end())

私が理解したいのは、関数の本体内での型名の使用法、パラメーター宣言です。

元。:

template< typename CharT >
struct basic_attribute_values_view< CharT >::implementation
{

public:
..
..
void adopt_nodes( **typename attribu**te_set_type::const_iterator& it, **typename attribut**e_set_type::const_iterator end)
    {
        for (; it != end; ++it)
            push_back(it->first, it->second.get());
    }

別のファイルで私は:

template< typename CharT >
class basic_attribute_set
{
    friend class basic_attribute_values_view< CharT >;

    //! Self type
    typedef basic_attribute_set< CharT > this_type;

public:
    //! Character type
    typedef CharT char_type;
    //! String type
    typedef std::basic_string< char_type > string_type;
    //! Key type
    typedef basic_slim_string< char_type > key_type;
    //! Mapped attribute type
    typedef shared_ptr< attribute > mapped_type;

    //! Value type
    typedef std::pair< const key_type, mapped_type > value_type;
    //! Allocator type
    typedef std::allocator< value_type > allocator_type;
    //! Reference type
    **typedef typename allocator_type::reference reference;**
4

3 に答える 3

13

typenameいわゆる「依存型」に使用する必要があります。これらはテンプレート引数に依存するタイプであり、テンプレートがインスタンス化されるまでわかりません。おそらく、例を使用して最もよく説明されます。

struct some_foo {
  typedef int bar;
};

template< typename Foo >
struct baz {
  typedef Foo::bar barbar; // wrong, shouldn't compile

  barbar f(); // would be fine if barbar were a type

  // more stuff...
};

そのtypedef定義は、具体的な型でインスタンス化される前に、コンパイラがテンプレートの露骨な構文エラーをチェックできるようにするためにbarbar必要な定義です。その理由は、コンパイラがテンプレートを初めて見るとき(具体的なテンプレートパラメータでまだインスタンス化されていないとき)、コンパイラは型であるかどうかを認識しないためです。知っている限り、私はこのようなタイプでインスタンス化するつもりかもしれませんtypenameFoo::barbaz

struct some_other_foo {
  static int bar;
};

この場合、型ではなくオブジェクトFoo::barを参照し、の定義は構文的にナンセンスになります。型を参照しているかどうかがわからない場合、コンパイラは、インスタンス化されるまで、最も愚かなタイプミスでさえも直接または間接的に使用しているものをチェックする機会がありません。適切なを使用すると、次のようになります。baz::barFoo::barbazbarbarbaztypenamebaz

template< typename Foo >
struct baz {
  typedef typename Foo::bar barbar;

  barbar f();

  // more stuff...
};

これで、コンパイラは少なくともFoo::bar、それが型の名前であることになっていることを認識します。これによりbarbar、型の名前も作成されます。したがって、の宣言f()も構文的にOKです。

ちなみに、タイプの代わりにテンプレートにも同様の問題があります。

template< typename Foo >
struct baz {
  Foo::bar<Foo> create_wrgl(); // wrong, shouldn't compile
};

Foo::barコンパイラーがそれが何であるかを「見る」とき、それはbar<Foo比較である可能性があり、コンパイラーは末尾のについて混乱したままになり>ます。Foo::barここでも、テンプレートの名前であると思われるヒントをコンパイラーに与える必要があります。

template< typename Foo >
struct baz {
  Foo::template bar<Foo> create_wrgl();
};

注意:特に、Visual C ++は適切な2フェーズルックアップを実装していません(本質的には、インスタンス化されるまでテンプレートを実際にチェックしません)。typenameそのため、またはを見逃した誤ったコードを受け入れることがよくありますtemplate

于 2009-10-21T12:43:38.417 に答える
6

キーワードのポイントは、typenameそれが明白でない状況で、何かが型名であることをコンパイラーに伝えることです。この例を見てください:

template<typename T>
void f()
{
    T::foo * x;
}

型はT::foo、ポインターを宣言していることを意味しますか、それともT::foo静的変数であり、乗算を行っていますか?

コンパイラーは、テンプレートを読み取るときにTが何であるかを認識していないため、2つのケースのどちらが正しいかを認識していません。

標準では、コンパイラは後者の場合を想定し、次のように、キーワードT::fooが前に付いている場合にのみタイプ名として解釈する必要があると規定されています。typename

template<typename T>
void f()
{
    typename T::foo* x; //Definitely a pointer.
}
于 2009-10-21T12:34:27.280 に答える
0

あなたのコードに:

void func(typename sometype)
{
    .....typename some_other_type;
    ..
}

上記のコードがテンプレートの一部でない場合、古いバージョンのg ++​​でない限り、g++を使用してコンパイルすることはできません。

私の経験では、FC9またはGNU C / ++バージョン4.2xはエラーとして報告し、次のように文句を言います。

typename only can be used in template code

FC8またはGNUC/++4.1xはそうではないかもしれませんが。

参照してください

http://code.google.com/p/effocore/source/browse/trunk/devel/effo/codebase/addons/inl/include/ringed_inl.h
and 
http://code.google.com/p/effocore/source/browse/trunk/devel/effo/codebase/addons/inl/include/cont_inl.h

その他のテンプレートとタイプ名の例については。

于 2009-10-21T12:51:06.007 に答える