Рассмотрим следующий код:внешне определяется указатель на функцию в качестве аргумента шаблона
main.cpp:
#include <iostream>
typedef void (* fncptr)(void);
extern void externalfunc(void);
template<void(* test)(void)>
class Bar
{
public:
Bar() { test(); }
};
void localfunc()
{
std::cout << "Hello World" << std::endl;
}
constexpr fncptr alias = localfunc;
extern fncptr externalAlias;
int main(int argc, char* argv[])
{
Bar<localfunc> b;
Bar<alias> b2; // This wouldn't compile if alias wasn't constexpr
Bar<externalfunc> b3;
// Bar<externalAlias> b4;
return 0;
}
и external.cpp:
#include <iostream>
typedef void (* fncptr)(void);
void externalfunc()
{
std::cout << "Hello external world" << std::endl;
}
fncptr externalAlias = externalfunc;
Теперь проблема мне нужно что-то вроде 4-я строка в основной функции для работы. Я получаю эти объявления функций из внешней библиотеки C, поэтому я не могу их трогать. В настоящее время 4-я строка не компилируется. gcc 4.6 говорит, что «это должен быть адрес функции с внешней связью». На самом деле это также говорит об этом, если вы делаете alias
не constexpr, поэтому фактическое значение (я думаю) должно интерпретироваться как «Я не знаю, на 100% уверен, что адрес функции, который вы мне даете, постоянный, который мне нужен для создания экземпляра этого шаблона ». Есть ли способ обойти это, так как я не могу объявить externalalias
как constexpr
в main.cpp
?
Прежде чем вы придете с альтернативными решениями: я уже пытаюсь получить эту работу, просто передав указатели на функцию через конструктор и сохраните их локально, но мне все же интересно, могу ли я заставить рабочую версию шаблона работать :).
Как компилятор должен знать, что такое значение 'externalAlias', чтобы он мог создать экземпляр шаблона? –
Да, он не знает этого значения 'externalAlias', но это переменная и, следовательно, он знает расположение этой переменной во время компиляции, поэтому она может создавать шаблон. (как видно в другом ответе (т. е. мой ответ :-))). –
Почему вы хотите сделать специализацию класса с помощью шаблона? Для этого и есть наследование. (т. е. test() должен быть просто виртуальным методом Bar), а затем иметь реализации теста в производных классах, которые соответствуют localfunc, alias, externfunc и т. д. Или, еще лучше, Bar - это просто отдельный класс и передается экземпляр класса и «ITest» в его конструкторе. Выполнение сложных штук с помощью шаблонов приводит к тому, что недопустимый код для других наследует. – selbie