考虑以下头文件:
// Foo.h
class Foo {
public:
template <typename T>
void read(T& value);
};
我希望在Foo::read
中包含的所有类型的源文件中显式实例化boost::mpl::vector
成员函数模板:
// Foo.cc
#include <boost/mpl/vector.hpp>
#include <boost/mpl/begin_end.hpp>
#include "Foo.h"
template <typename T>
void Foo::read(T& value) { /* do something */ }
typedef boost::mpl::vector<int, long, float> types;
// template Foo::read<int >(int&);
// template Foo::read<long >(long&);
// template Foo::read<float>(float&);
// instantiate automatically ???
有可能吗?提前谢谢,丹尼尔。
修改
我找到了一些解决方案 - 似乎在结构的构造函数中指定一个指向Foo::read<T>
的指针,然后声明该变量,导致实例化:
// intermezzo
template <typename T> struct Bar {
Bar<T>() {
void (Foo::*funPtr)(T&) = &Foo::read<T>;
}
};
static Bar<int > bar1;
static Bar<long > bar2;
static Bar<float> bar3;
那么这个过程可以按如下方式自动化:
// Foo.cc continued
template <typename B, typename E>
struct my_for_each {
my_for_each<B, E>() {
typedef typename B::type T; // vector member
typedef void (Foo::*FunPtr)(T&); // pointer to Foo member function
FunPtr funPtr = &Foo::read<T>; // cause instantiation?
}
my_for_each<typename boost::mpl::next<B>::type, E> next;
};
template<typename E>
struct my_for_each<E, E> {};
static my_for_each< boost::mpl::begin<types>::type,
boost::mpl::end<types>::type > first;
但我不知道这个解决方案是否便携且标准符合? (适用于Intel和GNU编译器。)
答案 0 :(得分:1)
我不久前有同样的要求,并且通过简单的函数模板实例化获得了良好的结果:
template <class... T>
void forceInstantiation(typedef boost::mpl::vector<T...>*) {
using ex = int[];
(void)ex{(void(&Foo::read<T>), 0)..., 0};
// C++17
// (void)((void(&Foo::read<T>), ...));
}
template void forceInstantiation(types*);
答案 1 :(得分:0)
我不确定这是否是您问题的解决方案,但也许您可以使用模板专业化。
新标题:
// Foo.h
template < typename T >
struct RealRead;
class Foo {
public:
template <typename T>
void read(T& value);
};
template <typename T>
void Foo::read(T& value)
{
RealRead< T >::read( value );
}
新来源:
template < >
struct RealRead< int >
{
static void read( int & v )
{
// do read
}
};
template < >
struct RealRead< float >
{
static void read( float & v )
{
// do read
}
};
//etc
// explicitly instantiate templates
template struct RealRead< int >;
template struct RealRead< float >;
答案 2 :(得分:0)
您可以使用template class Foo<T>;
至于批量实例化,我认为不可能。也许使用可变参数模板可以创建一个Instantiate类,因此像Instantiate<Foo, int, short, long, float, etc>
这样的东西会实例化相应的模板,但除此之外,你必须求助于手动实例化。
答案 3 :(得分:0)
显式实例化具有特殊的语法和编译器的特殊含义,因此不能用元编程完成。
您的解决方案会导致实例化,但不会显式实例化。
答案 4 :(得分:0)
我认为没有必要,也不可能。
只要在模板函数实现中明确定义了类型,就可以直接使用(调用)函数Foo:read(bar),用于任何类型的变量条。编译器会自动将您的参数变换为类型&#34; T&#34;。
例如:
template <class T>
Foo::read(T & var)
{
std::cin >> var;
}
当T是cin支持的流式传输时,T是明确定义的。
示例将是自包含的,如果&#34; Foo ::&#34;已移除。我的意思是,对于&#34; Foo ::&#34;,您应该在某处定义一个类Foo或一个名称空间Foo,以使其工作。
但请注意,模板应始终放在.h文件中,而不是.cpp文件(只需使用关键字&#34搜索网络; c ++文件无法在cpp文件中实现&#34;
答案 5 :(得分:0)
如果您打算仅在单个模块中使用您的课程(即您不会将其导出),您可以使用boost / mpl / for_each。不会导出以这种方式定义的模板函数(使用mpl / for_each)(即使在类名或函数签名之前声明__declspec(export)):
// Foo.cpp
#include <boost/mpl/vector.hpp>
#include <boost/mpl/for_each.hpp>
template<class T>
void read(T& value)
{
...
}
using types = boost::mpl::vector<long, int>;
//template instantiation
struct call_read {
template <class T>
void operator()(T)
{
T t; //You should make sure that T can be created this way
((Foo*)nullptr)->read<T>(t); //this line tells to compiler with templates it should instantiate
}
};
void instantiate()
{
boost::mpl::for_each<types>(call_read());
}
如果您需要导出/导入结构和模板方法,则使用boost / preprocessor
进行解决方案// Foo.h
#ifdef <preprocessor definition specific to DLL>
# define API __declspec(dllexport)
#else
# define API __declspec(dllimport)
#endif
class API Foo {
public:
template<class T> void read(T& value);
};
// Foo.cpp
#include <boost/preprocessor/seq/for_each.hpp>
#include <boost/preprocessor/seq/enum.hpp>
#include <boost/mpl/vector.hpp>
template<class T>
void read(T& value)
{
...
}
//using this macro you can define both boost::mpl structure AND instantiate explicitly your template function
#define VARIANT_LIST (std::wstring)(long)(int)
using types = boost::mpl::vector<BOOST_PP_SEQ_ENUM(VARIANT_LIST)>;
//Here we should use our API macro
#define EXPLICIT_INSTANTIATION(r, d, __type__) \
template API void Foo::read<__type__>(__type__&);
BOOST_PP_SEQ_FOR_EACH(EXPLICIT_INSTANTIATION, _, VARIANT_LIST)
如果你不需要这个额外的功能,我猜第一个解决方案就更清晰了