【问题标题】:Specific Template Friendship in C++C++ 中的特定模板友谊
【发布时间】:2012-09-29 20:01:46
【问题描述】:

我有一个关于 C++ 中特定模板友谊的问题。 在C++ Primer一书中,具体的模板友情是这样写的:

 template <class T> class Foo3;
 template <class T> void templ_fcn3(const T&);
 template <class Type> class Bar {
     // each instantiation of Bar grants access to the
     // version of Foo3 or templ_fcn3 instantiated with the same type
     friend class Foo3<Type>;
     friend void templ_fcn3<Type>(const Type&);
     // ...
 };

特别之处在于有

<Type>

friend 语句中的类或函数名称之后。

但是,在实践中,如果我这样写:

template <class Type> class T_CheckPointer;
template <class T> T_CheckPointer<T> operator+(const T_CheckPointer<T> &, const size_t n);

template <typename Type>
class T_CheckPointer {

    // Specific Template Friendship
    friend T_CheckPointer<Type>
    operator+ <Type> (const T_CheckPointer<Type> &, const size_t n);

// other code...

}

模板函数在实例化过程中会出错。

如果我改变了

// Specific Template Friendship
friend T_CheckPointer<Type>
    operator+ <Type> (const T_CheckPointer<Type> &, const size_t n);

// Specific Template Friendship
friend T_CheckPointer<Type>
    operator+ <> (const T_CheckPointer<Type> &, const size_t n);

删除函数名后面的type,就可以了。

谁能告诉我原因?


有关信息,当我调用时有 错误消息

int iarr[] = {1, 2, 3, 4};
T_CheckPointer<int> itcp(iarr, iarr+4);

错误信息:

/usr/include/c++/4.4/bits/stl_iterator_base_types.h: In instantiation of ‘std::iterator_traits<int>’:
/usr/include/c++/4.4/bits/stl_iterator.h:96:   instantiated from ‘std::reverse_iterator<int>’
../Classes/T_CheckPointer.hpp:31:   instantiated from ‘T_CheckPointer<int>’
../PE16.cpp:520:   instantiated from here
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:127: error: ‘int’ is not a class, struct, or union type
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:128: error: ‘int’ is not a class, struct, or union type
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:129: error: ‘int’ is not a class, struct, or union type
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:130: error: ‘int’ is not a class, struct, or union type
/usr/include/c++/4.4/bits/stl_iterator_base_types.h:131: error: ‘int’ is not a class, struct, or union type

【问题讨论】:

  • @enobayram,感谢您的关注,我已将它们放在文章中。
  • 您能否提供一个显示问题的 minimal 示例(在例如 Ideone 上编译)?您是否尝试升级到 gcc 4.7?

标签: c++ templates friend access-control


【解决方案1】:

这是一个最小的例子:

template<typename T> struct U { typedef typename T::X X; };
template<typename T> void foo(typename U<T>::X);

template<typename T> struct S;
template<typename T> void foo(S<T>);
template<typename T> struct S { friend void foo<T>(S<T>); };

template struct S<int>;

friend 声明失败的原因是,通过提供模板参数的完整列表,您要求编译器专门化所有可用的函数模板并选择与签名最匹配的函数模板。 foo 的第一个定义的特化导致特化 U 的参数导致程序不正确。

如果你省略了模板参数,它将从参数中推导出来。由于这样的模板参数推导是根据14.8.2 [temp.deduct]进行的,特别是14.8.2p8适用,这意味着U的特化中的替换失败不是错误(SFINAE)。

这是一个很好的理由,可以在任何可以从上下文中推断出模板参数的地方省略模板参数(例如,这里的函数或运算符参数类型)。请注意,您仍然需要提供 &lt;&gt; 括号以确保 operator + 被读取为 template-id (14.5.4 [temp.friend]) .

【讨论】:

  • +1 这是一个非常好的答案!另请注意,&lt;&gt; 括号是为了防止选择非模板函数而不是模板函数。请参阅 Herb Sutter 的这篇旧专栏 drdobbs.com/befriending-templates/184403853
  • +1 非常感谢您的回复!你的回答很清楚。 @ecatmur
猜你喜欢
  • 2021-10-30
  • 1970-01-01
  • 2014-09-30
  • 2021-12-06
  • 1970-01-01
  • 1970-01-01
  • 2015-12-11
  • 1970-01-01
相关资源
最近更新 更多