У меня есть вопрос для конкретного шаблона дружбы в 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>
после имени класса или функции в друг заявление.
Однако на практике, если я напишу это:
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);
удалив слово тип после имени функции все будет хорошо.
Кто-нибудь может сказать мне причину?
Для информации есть сообщение об ошибке когда я звоню
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
Вот минимальный пример:
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).
Это хорошая причина для исключения аргументов шаблона везде, где они могут быть выведены из контекста (например, здесь типы параметров функции или оператора). Обратите внимание, что вам все еще нужно предоставить <>
скобки, чтобы гарантировать, что operator +
читается как Шаблон-идентификатор (14.5.4 [temp.friend]).
Других решений пока нет …