A specific friendship pattern in C ++

I have a question for a specific friendship of templates in C ++. in the C ++ Primer book, concrete template friendships are written as follows:

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&); // ... }; 

The special point is that there is

 <Type> 

after the class or function name in a friend statement.

However, in practice, if I write this:

 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... } 

An error will be made for the template function during instances.

And if I change

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

to

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

deleting the type word after the function name, then everything will be fine.

Can anyone tell me the reason?


For information, a message appears. when i call

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

error message:

 /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 
+7
source share
1 answer

Here's a minimal example:

 template<typename T> struct U { typedef typename T::XX; }; 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>; 

The reason friend refuses is that, by providing a complete list of template arguments, you request that the compiler specialize in all available function templates and select the one that best matches the signature. Specialization of the first definition of foo leads to specialization of U with an argument, which leads to a poorly formed program.

If you omit the template argument instead, it will be inferred from the arguments. Since this output of the template argument is performed in accordance with 14.8.2 [temp.deduct] , and in particular, 14.8.2p8 is applied, which means that the replacement failure in the U specialization is not an error (SFINAE).

This is a good reason to omit the template arguments anywhere where they can be inferred from the context (for example, functions or types of operator parameters here). Note that you still need to provide the brackets <> to make sure operator + is read as the template identifier ( 14.5.4 [temp.friend] ).

+4
source

All Articles