Specific Template Friendship in C++
access-control, c++, friend, templates
Solution
Here's a minimal example:
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>;
The reason the `friend` declaration fails is that by providing a full list of template arguments you are requesting the compiler specialize all available function templates and pick the one that best matches the signature. Specialization of the first definition of `foo` results in specializing `U` with an argument that results in an ill-formed program.
If instead you omit the template argument, it will be deduced from the arguments. As such template argument deduction is performed according to 14.8.2 [temp.deduct], and in particular 14.8.2p8 applies, which means that the substitution failure in the specialization of `U` is not an error (SFINAE).
This is a good reason to omit template arguments anywhere they can be deduced from context (e.g. here the function or operator parameter types). Note that you still need to provide the `<>` brackets to ensure that the `operator +` is read as a template-id (14.5.4 [temp.friend]).
Problem
I have a question for Specific Template Friendship in C++. in the book C++ Primer, the specific template friendship is written like this: ``` 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 the 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... } ``` There will be a error during instantiations for the template function. 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); ``` by deleting the word type after the function name, then all will be okay. Anyone can tell me the reason? For information, there is the error message 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 ```