2009-10-21 2 views
4

사실 저는 인텔 컴파일러로 일부 라이브러리를 컴파일하는 데 문제가 있습니다.템플릿 문제 (템플릿 함수 매개 변수가 아닌 'typename')

이 라이브러리는 g ++로 올바르게 컴파일되었습니다.

문제는 템플릿 때문에 발생합니다. 내가 이해하고 싶은 것은 **typename**의 선언입니다 같은 함수 본문 내부되지 템플릿 함수 매개 변수와 변수 선언

예 :

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

컴파일 오류 다음 코드 농산물의 종류 (인텔), (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()) 

나는 이사회 내부의 유형 이름의 사용을 이해하고 싶습니다 무엇 함수의 y, 매개 변수 선언. 다른 파일에

예 :

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;** 
+0

컴파일러 오류가 발생한 코드가 있으면 쉽게 될 것입니다 (표시된 선이 표시된 경우). 구문에 '**'를 사용하면 코드 블록에서 작동하지 않습니다. –

+0

모든 iterator! = 예제에서는 simmilar 오류가 발생하므로 첫 번째 코드 예제에서 (it! = end;) 줄이됩니다. – bua

답변

12

당신은 소위에 대한 typename를 사용해야합니다 :

이 표준은 컴파일러는 후자의 경우를 가정하고,이처럼 typename 키워드가 오는 경우에만 유형 이름으로 T::foo을 해석해야한다고 지시 종속 형 "이라고합니다. 그것들은 템플릿 인자에 의존하는 유형이며, 템플릿이 인스턴스화 될 때까지 알지 못합니다. typedefbarbar 그것이 구체적으로 인스턴스화 전에 소란스러운 구문 오류 에 대한 템플릿을 확인 할 수 있도록 컴파일러 위해 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... 
}; 

난 것이 가장 예제를 사용하여 설명 아마 유형. 이유는 컴파일러가 템플릿을 처음 볼 때 (아직 구체적인 템플릿 매개 변수로 인스턴스화되지 않은 경우) 컴파일러는 Foo::bar이 유형인지 여부를 알지 못하기 때문입니다.이 알다시피, 나는 baz 의도는 경우 Foo::bar객체이 아닌 형식을 참조 할 것이다이 하나

struct some_other_foo { 
    static int bar; 
}; 

같은 유형의 인스턴스화 할 수 있으며 baz::bar의 정의는 구문 말도 안되는 것입니다. Foo::bar이 타입을 참조하는지 여부를 알지 못하면 컴파일러는 baz이 직접 또는 간접적으로 baz이 인스턴스화 될 때까지 가장 바보 같은 오타에도 barbar을 사용하는 것을 확인할 기회가 없습니다. 적절한 typename 사용 baz은 다음과 같습니다

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(); 
}; 

주의 : 여전히 본질적으로 (적절한 두 단계 조회를 구현하지 않습니다 ++ 특히 비주얼 C를 : 실제로 인스턴스화 될 때까지 템플릿을 확인하지 않습니다.) 따라서 종종 typename 또는 template이 누락 된 오류 코드를 허용합니다. 코드시

+2

+1 단계 2 단계 조회에 대한 설명입니다. 따라서 조언 : 가능한 경우 적어도 두 개의 다른 컴파일러로 코드를 컴파일하십시오. – Francesco

3
typename 키워드의 요점은 그렇지 않은 경우 상황에서 뭔가가 유형 이름은 컴파일러를 알리는 것입니다

분명한. 이 예제를 보자

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

우리가 포인터를 선언하는 의미 유형 T::foo, 아니면 T::foo 정적 변수이며, 우리는 곱셈을하는거야?

컴파일러는 템플릿을 읽을 때 T가 될 수 있는지 알지 못하기 때문에 두 경우 중 어느 것이 맞는지 잘 모릅니다.

template<typename T> 
void f() 
{ 
    typename T::foo* x; //Definitely a pointer. 
} 
0

:

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

위의 코드는 다음이 g의 이전 버전 않는 ++, ++ g을 사용하여 컴파일 할 수없는, 템플릿의 일부가 아닌 경우. 내 경험, FC9 또는 오류로보고 GNU C/++ 버전 4.2로

, 그것은 불평 것 :

typename only can be used in template code 

동안 FC8 또는 GNU C/++ 4.1하지 않을 수 있습니다.

더 템플릿과 유형 이름 예제

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 

를 참조하십시오.

관련 문제