4

实际上我在用英特尔编译器编译一些库时遇到了问题。

这个库已经用 g++ 正确编译。

问题是由模板引起的。我想了解的是 **typename**在函数体内声明 as not 模板函数参数和变量声明

例子:

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需要一个typename,以便编译器能够在使用具体类型实例化模板之前检查模板是否存在明显的语法错误。原因是,当编译器第一次看到模板时(当它还没有用具体的模板参数实例化时),编译器不知道是否Foo::bar是一个类型。据它所知,我可能打算baz用这样的类型实例化

struct some_other_foo {
  static int bar;
};

在这种情况下Foo::bar将引用一个object,而不是一个类型,并且 of 的定义baz::bar将是句法废话。在不知道是否Foo::bar引用类型的情况下,编译器没有机会检查baz直接或间接使用的任何内容,barbar即使是最愚蠢的拼写错误,直到baz被实例化。使用正确的typenamebaz看起来像这样:

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

  barbar f();

  // more stuff...
};

现在编译器至少知道它Foo::bar应该是一个类型的名称,它也产生barbar了一个类型名称。所以声明 off()在语法上也可以。

顺便说一句,模板而不是类型也有类似的问题:

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++ 仍然没有实现正确的两阶段查找(本质上:它在模板被实例化之前并不真正检查模板)。因此,它经常接受遗漏 atypename或 a 的错误代码template

于 2009-10-21T12:43:38.417 回答
6

关键字的重点typename是告诉编译器某些东西是类型名,在不明显的情况下。举个例子:

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

T::foo类型,意味着我们声明了一个指针,还是T::foo一个静态变量,我们正在做一个乘法?

由于编译器在读取模板时不知道 T 可能是什么,因此它不知道这两种情况中的哪一种是正确的。

标准规定编译器应该假设后一种情况,并且只有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 或 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

更多模板和类型名示例。

于 2009-10-21T12:51:06.007 回答