Рассмотрим этот код:Как избежать ошибки переопределения в случае определения класса функции в классе?
template<typename T>
class Base
{
template<typename U>
friend void f(void *ptr) {
static_cast<Base<U>*>(ptr)->run();
}
protected:
virtual void run() = 0;
};
class A : public Base<A>
{
protected:
virtual void run() {}
};
/*
class B : public Base<B>
{
protected:
virtual void run() {}
};
*/
Он компилирует нормально сейчас (ideone). Но если я раскомментировать определение B
, то это дает следующее сообщение об ошибке (ideone):
prog.cpp: In instantiation of ‘Base<B>’:
prog.cpp:20: instantiated from here
prog.cpp:6: error: redefinition of ‘template<class U> void f(void*)’
prog.cpp:6: error: ‘template<class U> void f(void*)’ previously defined here
Я знаю (хорошо, я думаю, я знаю) причину, почему он дает эту ошибку.
Так что мой вопрос:
Как избежать ошибок переопределения в случае в классе определения шаблона друга функции?
До тех пор, пока я даю определение основного шаблона (не специализации) внутри класса, я получу эту ошибку. Существует также другая проблема с определением первичного шаблона таким образом: он делает все экземпляры шаблона f
friend
всех экземпляров шаблона класса Base
, которого я также хотел бы избежать. Я хочу сделать f<T>
другом Base<T>
, но не f<U>
другу Base<T>
, если U
и T
не то же самое. В то же время я также хочу дать определение внутри класса. Является ли это возможным?
Я не вижу причин, почему компилятор должен без ошибок на этом, и это, кажется, лязг люди не видят причины тоже, как он компилирует с clang. – PlasmaHH
GCC и MSVC10 оба дают ошибку, если я раскомментирую определение 'B'. – Nawaz
@PlasmaHH: поскольку функция friend не является функцией-членом и поэтому может быть не зависящей от аргументов шаблона класса. –