Создание бесплатной функции шаблона внутри класса шаблона
Мне нужно создать бесплатную функцию шаблона (FTF) внутри класса шаблона (TC). FTF принимает в качестве параметра шаблона один из параметров шаблона TC. TC также содержит общие указатели на эти FTF, и эти функции вызываются через указатели.
Шаг создания указателя на FTF недостаточен для его создания, и я получаю ошибки компоновщика из цепочки инструментов GCC. MSDN иллюстрирует спецификацию FTF как таковую - однако мой экземпляр FTF зависит от параметра шаблона моего TC, и, следовательно, экземпляр FTF не может быть помещен в свободную область.
Это возможно? Я прилагаю некоторый основной сгенерированный код, проблема в конструкторе class test_service
где я назначаю указатель свободной функции в пользовательский контейнер. Я получаю ошибку компоновщика, сообщающую, что свободная функция не может быть найдена (необоснованно). Я знаю, что указание вызова функции шаблона в классе где-нибудь приведет к созданию экземпляра, однако я собираюсь делать вызов только через указатель.
#include "rpc_common.h"
#include <boost/cstdint.hpp>
namespace rubble { namespace rpc {
struct test_service_dummy_tag{};
template<typename T>
class test_service_skel
{
public:
bool Init() {}
bool TearDown() {}
bool test_one(TestRequest,TestResponse){};
private:
};
template<typename T_IMPL>
bool test_service_test_one(T_IMPL & impl,ClientRequest & request)
{
return 0;
}
template<typename T_IMPL=test_service_skel<test_service_dummy_tag> >
class test_service
{
public:
test_service()
{
// uncomment the following two lines and a instantiation will occur.
// ClientRequest cr;
//test_service_test_one<T_IMPL>(m_impl,cr);
m_dispatch_table.SetEntry( Oid("test_one",0),(void *) & test_service_test_one<T_IMPL>);
}
bool Init() { return m_impl.Init(); };
bool TearDown() { return m_impl.TearDown(); };
private:
T_IMPL m_impl;
OidContainer<Oid,void *> m_dispatch_table;
};
} }
РЕДАКТИРОВАТЬ: автономная минимальная версия
class test_skel
{
bool test_function()
{
return true;
}
};
template<typename T>
bool test_function()
{
}
template<typename T = test_skel>
class test
{
public:
test()
{
dispatch = (void *) & test_function<T>;
}
void * dispatch;
};
int main()
{
test<> t;
return 0;
}
2 ответа
Нет проблем, если вы не используете void*
, т.е.: http://www.ideone.com/eRgUG
Однако, если вы настаиваете на хранении указателя в void*
, затем вам нужно сначала взять адрес, используя указатель определенной функции, а затем привести - например,
bool (*temp)() = &test_function<T>;
dispatch = reinterpret_cast<void*>(temp); // YUCK
Это дает компилятору достаточно контекста для генерации адреса для вас.
Ааа - только что видел ответ DeadMG, функция для генерации void*
аккуратнее...
Ваш автономный пример не скомпилирует для меня странную ошибку о перегруженных функциях, когда перегрузка не происходит с MSVC. Однако мне удалось обойти это.
class test_skel
{
bool test_function()
{
return true;
}
};
template<typename T> void* to_void_pointer(T t) {
return reinterpret_cast<void*>(t);
}
template<typename T>
bool test_function()
{
return true;
}
template<typename T = test_skel>
class test
{
public:
test()
{
dispatch = to_void_pointer(&test_function<T>);
}
void * dispatch;
};
int main()
{
test<> t;
return 0;
}
Это компилируется чисто. Я подозреваю, что любое поведение, которое вы видите, и которое я видел, является ошибкой компилятора.