Я хочу переслать объявление переменных шаблонов в заголовочном файле, а затем иметь фактические экземпляры в отдельном модуле компиляции.
Я был убежден, что шаблоны переменных C ++ 14 работают так же, как статические переменные класса. К сожалению, похоже, что это не совсем так, и это мешает мне заранее объявить мои переменные шаблоны.
template <typename T> struct Variable {
static int variable;
};
template <typename T>
extern int variable;
int main() {
(void) Variable<char>::variable;
// (void) variable<char>; // <-- line 10
}
template <> int Variable<char>::variable = 42;
template <> int variable<char> = 23;
Пример кода выше компилируется и запускается как есть в GCC. Но раскомментирующая строка 10 выдает ошибку времени компиляции:
specialization of 'variable<char>' after instantiation
template <> int variable<char> = 23;
^
Я думаю, что вы на правильном пути.
Хитрость заключается в следующем: ни в одном из модулей перевода не создавайте экземпляр шаблона до того, как вы специализовались.
Например:
// test.h
#ifndef TEST_H
#define TEST_H
template <typename T>
extern int variable;
template <> extern int variable<char>;
template <> extern int variable<int>;
#endif // TEST_H
Затем:
// test2.cpp
#include "test.h"
template <> int variable<char> = 23;
template <> int variable<int> = 24;
И наконец:
// test.cpp
#include "test.h"#include <iostream>
int
main()
{
std::cout << variable<char> << '\n';
std::cout << variable<int> << '\n';
}
Для меня это выводы:
23
24
Обновить
Агар Т.С. В комментариях ниже указано, что специализации должны быть объявлены перед первым использованием, поэтому я обновил «test.h» выше, чтобы сделать это.
Обновление 2
Кажется, есть некоторые расхождения в реализации. Clang, кажется, справиться с этим штрафом:
template <typename T>
extern int variable;
template <> extern int variable<char>;
template <> extern int variable<int>;
#include <iostream>
int
main()
{
std::cout << variable<char> << '\n';
std::cout << variable<int> << '\n';
}
template <> int variable<char> = 23;
template <> int variable<int> = 24;
http://melpon.org/wandbox/permlink/DGYKvvoPbmRIHaFi
Однако gcc выдает ошибку:
prog.cc:4:13: error: explicit template specialization cannot have a storage class
template <> extern int variable<char>;
^~~~~~
prog.cc:5:13: error: explicit template specialization cannot have a storage class
template <> extern int variable<int>;
^~~~~~
Я искал стандарт и список основных проблем, и я не могу найти ничего, что указывало бы, что один компилятор или другой верны. Если кто-то увидит такие доказательства, я с радостью включу их в этот ответ.
Других решений пока нет …