Внешний шаблонный класс и не шаблонные функции друзей

Я начал играть с extern шаблонов, и я наткнулся на проблему, по которой я не могу найти никакой соответствующей информации. Скажем, у меня есть шаблон класса с функцией друга, не являющейся шаблоном (определенной в объявлении шаблона класса). Я заявляю некоторые extern шаблонные экземпляры для класса, но как мне также объявить функцию друга как extern?

Вот пример кода:

// --- test.h ---

template <typename T>
class Foo {
private:
T value;
public:
friend void some_friend_function(Foo<T>& obj) {
obj.value -= T(42);
};

void some_member_function(T rhs) { value += rhs; };

};

extern template class Foo<int>;
//extern void some_friend_function(Foo<int>&);  // I tried this also...// --- test.cpp ---

#include "test.h"
template class Foo<int>;
//void some_friend_function(Foo<int>&);         // ... with this.

Когда я компилирую вышеизложенное (с закомментированными строками или без них), я получаю только следующий экспортированный символ:

0000000000000000 W _ZN3FooIiE20some_member_functionEi

Таким образом, функции-шаблоны, не являющиеся шаблонами, определенно не создаются (и extern‘d) наряду с явной реализацией шаблона класса. Это нормально? По крайней мере, это то, что производит GCC (протестировано на 4.6.3 и 4.7.2).

Есть ли способ, которым я могу сделать функцию друга отмеченной как extern? Я знаю, что это не огромная проблема, так как я могу с радостью жить, когда функции друзей создаются по мере необходимости (т.е. не extern), но мне интересно знать, есть ли способ сделать это, если нет Это было упущением или преднамеренным?

РЕДАКТИРОВАТЬ: очевидные обходные пути

Мой вопрос конкретно о функциях друзей, не относящихся к шаблону, а не о поиске обходного пути, чтобы избежать проблемы, что тривиально. Первый очевидный обходной путь заключается в следующем:

template <typename T>
class Foo {
private:
T value;
public:
template <typename U>
friend void some_friend_function(Foo<U>& obj) {
obj.value -= T(42);
};
};

extern template class Foo<int>;
extern template void some_friend_function(Foo<int>&);

// --- in cpp file: ---

template class Foo<int>;
template void some_friend_function(Foo<int>&);

И еще один, который соответствует более близко, но более хлопотно, это:

template <typename T> class Foo;  // forward-declare.

template <typename T>
void some_friend_function(Foo<T>&);  // declaration.

template <typename T>
class Foo {
private:
T value;
public:
friend void some_friend_function<>(Foo<T>& obj);  // befriend the T-specialization.
};

template <typename T>
void some_friend_function(Foo<T>& obj) {  // definition.
obj.value -= T(42);
};

extern template class Foo<int>;
extern template void some_friend_function(Foo<int>&);

// --- in cpp file: ---

template class Foo<int>;
template void some_friend_function(Foo<int>&);

4

Решение

Эффект «внешнего шаблона класса» заключается в объявлении явного экземпляра доступным. Эффект явных объявлений создания экземпляров не применяется к встроенным функциям или специализациям шаблонов (14.7.2 [temp.explicit] параграф 10):

За исключением встроенных функций и специализаций шаблонов классов, явные объявления экземпляров подавляют неявное создание экземпляров сущности, к которой они относятся.

Так как friend Определение функции в определении класса обязательно inline функция, она останется inline функция не зависит от явного объявления экземпляра шаблона (и, как вы правильно заметили, это не шаблон и в любом случае не следует правилам создания экземпляра шаблона).

0

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]