템플릿 문제 (템플릿 함수 매개 변수가 아닌 '타이프 이름')
-
05-07-2019 - |
문제
실제로 인텔 컴파일러로 일부 라이브러리를 컴파일하는 데 문제가 있습니다.
이 동일한 라이브러리는 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;**
해결책
사용해야합니다 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
필요한 것입니다 typename
컴파일러가 홍보 구문 오류를 템플릿을 확인할 수 있도록 ~ 전에 콘크리트 유형으로 인스턴스화됩니다. 그 이유는 컴파일러가 처음으로 템플릿을 볼 때 (아직 콘크리트 템플릿 매개 변수로 인스턴스화되지 않았을 때) 컴파일러는 Foo::bar
유형입니다. 아시다시피, 나는 의도 할 수 있습니다 baz
이와 같은 유형과 인스턴스화됩니다
struct some_other_foo {
static int bar;
};
어떤 경우 Foo::bar
would refer to an 물체, 유형이 아니라 정의 baz::bar
구문 넌센스 일 것입니다. 알지 못하고 Foo::bar
유형을 말하면 컴파일러는 내에서 아무것도 확인할 기회가 없습니다. baz
직간접 적으로 사용하고 있습니다 barbar
가장 어리석은 오타조차도 baz
인스턴스화됩니다. 적절한 사용 typename
, baz
이렇게 보인다 :
template< typename Foo >
struct baz {
typedef typename Foo::bar barbar;
barbar f();
// more stuff...
};
이제 컴파일러는 적어도 그것을 알고 있습니다 Foo::bar
유형의 이름이어야합니다. barbar
유형 이름도. 그래서 선언 f()
구문도 좋습니다.
그건 그렇고, 유형 대신 템플릿과 비슷한 문제가 있습니다.
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 상 조회를 구현하지 않습니다 (본질적으로 : 템플릿이 인스턴스화 될 때까지 실제로 템플릿을 점검하지는 않습니다). 따라서 종종 a를 놓치는 잘못된 코드를 받아들입니다 typename
또는 a template
.
다른 팁
의 요점 typename
키워드는 컴파일러에게 분명하지 않은 상황에서 무언가가 타이프 이름임을 알리는 것입니다. 이 예를 들어보세요 :
template<typename T>
void f()
{
T::foo * x;
}
~이다 T::foo
유형, 즉 우리가 포인터를 선언하거나 T::foo
정적 변수이며 곱셈을하고 있습니까?
컴파일러는 템플릿을 읽을 때 어떤 t가 될 수 있는지 전혀 모르기 때문에 두 경우 중 어느 것이 올바른지 전혀 모른다.
표준은 컴파일러가 후자의 경우를 가정하고 해석해야한다고 지시합니다. T::foo
The TypeName으로 선행되는 경우 typename
다음과 같은 키워드 :
template<typename T>
void f()
{
typename T::foo* x; //Definitely a pointer.
}
코드에 :
void func(typename sometype)
{
.....typename some_other_type;
..
}
위의 코드가 템플릿의 일부가 아닌 경우 이전 버전의 G ++가 아니라면 g ++를 사용하여 컴파일 할 수 없습니다.
경험이 풍부한 FC9 또는 GNU C/++ 버전 4.2x는이를 오류로보고 할 것입니다.
typename only can be used in template code
FC8 또는 GNU C/++ 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
더 많은 템플릿 및 타이프 이름 예제.