У меня есть класс шаблона, который я объявляю в заголовке одним методом и не определяю этот метод в заголовке. В файле .cc, я определяю специализации этого метода, не объявляя их в заголовке. В другом файле .cc, я вызываю метод для различных параметров шаблона, для которых существуют специализации. Это выглядит так:
foo.h:
template<typename T>
class Foo {
public:
static int bar();
};
foo.cc:
#include "foo.h"
template<>
int Foo<int>::bar() {
return 1;
}
template<>
int Foo<double>::bar() {
return 2;
}
main.cc:
#include <iostream>
#include "foo.h"
int main(int argc, char **argv) {
std::cout << Foo<int>::bar() << std::endl;
std::cout << Foo<double>::bar() << std::endl;
return 0;
}
Эта программа успешно компилирует и связывает gcc 4.7.2 для всех стандартов С++ (С++ 98, gnu ++ 98, С++ 11 и gnu ++ 11). Выход:
1
2
Это имеет смысл для меня. Поскольку блок трансляции main.cc не видит определения bar()
или каких-либо специализаций, он ожидает, что вызовы bar()
будут использовать явные экземпляры неспециализированного определения bar()
в некоторой другой единицы перевода. Но так как изменение имени предсказуемо, специализации в foo.cc имеют те же имена символов, что и явные экземпляры неспециализированного определения, поэтому main.cc может использовать эти специализации без их объявления в этой единицы перевода.
Мой вопрос заключается в следующем: это несчастный случай, или это поведение обусловлено стандартом С++? Другими словами, этот переносимый код?
Наиболее актуальным предыдущим вопросом, который я смог найти, является Объявление специалиста по членству в классе шаблонов, но оно не охватывает этот конкретный случай.
(Если вам интересно, почему это имеет значение для меня, это потому, что я использую такой код как своего рода таблицу поиска во время компиляции, и это намного короче, если я не объявляю специализации. )