20

考虑以下头文件:

// Foo.h
class Foo {
    public: 
        template <typename T>
        void read(T& value);
};

我想Foo::read在源文件中为 a 中包含的所有类型显式实例化成员函数模板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 编译器。)

4

6 回答 6

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*);
于 2016-12-31T14:40:05.953 回答
0

显式实例化对编译器具有特殊的语法和特殊意义,因此不能用元编程来完成。

您的解决方案会导致实例化,但不会导致显式实例化。

于 2014-05-23T16:16:16.087 回答
0

我认为没有必要,也不可能。

您可以直接使用(调用)函数 Foo:read(bar) 来处理任何类型的变量 bar,只要该类型在模板函数实现中明确定义即可。编译器会自动将您的参数变形为类型“T”。

例如:

template <class T>
Foo::read(T & var)
{
    std::cin >> var;
}

当 T 是 cin 支持的流类型时,T 是明确定义的。

如果删除了“Foo::”,该示例将是独立的。我的意思是,对于“Foo::”,您应该在某个地方定义一个类 Foo 或命名空间 Foo,以使其工作。

但请注意,模板应始终放在 .h 文件中,而不是 .cpp 文件中(只需在网上搜索关键字“c++ 模板无法在 cpp 文件中实现”

于 2014-09-04T10:54:13.953 回答
0

您可以使用 Foo 为给定的 T 模板参数显式实例化template class Foo<T>;

至于批量实例化,我认为不可能。也许使用可变参数模板可以创建一个 Instantiate 类,以便Instantiate<Foo, int, short, long, float, etc>实例化适当的模板,但除此之外,您必须求助于手动实例化。

于 2011-07-01T15:38:52.860 回答
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 >;
于 2011-04-19T11:37:02.437 回答
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)

如果您不需要这个额外的功能,我猜第一个解决方案会更干净

于 2016-03-09T15:18:16.457 回答