C :在库中实例化许多模板

C++: Instantiate many templates in library

本文关键字:实例化 许多模      更新时间:2023-10-16

我有一个库,上面有一个尺寸的类:

foo.hpp

template <size_t N>
struct Foo {
   void bar();
};

foo.cpp

template <size_t N>
void Foo<N>::bar() {
...
};

我希望将编译版本用于特定尺寸列表,该尺寸将在CPP文件中定义。在伪代码中,类似这样的东西

foo.cpp

template <size_t N>
void Foo<N>::bar() {
...
};
for (const auto & size: {1,2,7,9})
    template struct Foo<size>;

现在,我正在手动执行此操作(每种类型(,但这很容易发生,因为我有几个文件应以相同的大小定义。

我知道我可以将所有内容都移至标头文件,并使用一些enable_if的选择来选择哪些尺寸有效。但是,我想隐藏实现细节。因此,当前的方法。

编辑:

fwiw,我希望避免宏。我认为,如果您想要一系列变量(例如1,2,3,4 ...(:

template<template<size_t> class E, size_t I = 1, std::enable_if_t<I >= 5> *unused = nullptr>
bool instatiator() {
  return true;
}
template<template<size_t> class E, size_t I = 1, std::enable_if_t<I < 5> *unused = nullptr>
bool instatiator() {
  E<I> e;
  return instatiator<E, I + 1>();
}
bool unused = instatiator<Encoder>();

,但我似乎无法做到这一点。

您可以使用x宏观方法:

有效_sizes.hpp

// Note: no include guards!!
PROCESS_SIZE(1)
PROCESS_SIZE(2)
PROCESS_SIZE(7)
PROCESS_SIZE(9)
#undef PROCESS_SIZE

foo.cpp

// ...
#define PROCESS_SIZE(n) template struct Foo<n>;
#include "valid_sizes.hpp"

bar.cpp

// ...
#define PROCESS_SIZE(n) some_other_use_of<n>;
#include "valid_sizes.hpp"

另外,您可以使用boost.preprocessor:

而不是手动列表

process_sizes.hpp

#pragma once
#define PROCESS_SIZES(macro, data) BOOST_PP_SEQ_FOR_EACH(macro, data, (1)(2)(7)(9))

一些标头文件

#define INSTANTIATE_CLASS(r, Name, size) template class Name<size>;

foo.cpp

#include "process_sizes.hpp"
// ...
PROCESS_SIZES(INSTANTIATE_CLASS, Foo)

bar.cpp

#include "process_sizes.hpp"
// ...
PROCESS_SIZES(INSTANTIATE_CLASS, Bar)
#define OTHER_SIZE_BASED_WORK(r, data, size) other_use_of<size>;
PROCESS_SIZES(OTHER_SIZE_BASED_WORK, whatever)

请注意,明确的实例定义必须在命名空间范围内发生,因此不可能将它们像您尝试过的instantiator一样。

还要注意,隐式实例化(例如,在要求将其定义的上下文中引用的班级引起的(在翻译单元之外不"可见",因此不能用作替代品显式实例。

换句话说,具有相同尺寸的列表需要不同的事情,需要复制每种用途的列表,使用宏或在C 编译管道之外使用自定义代码生成。我认为宏是其中最简单,最可维护的。

除了@angew答案:Xmacros可以以不同的方式进行,允许包括警卫,还避免在代码中间使用#include

有效_sizes.hpp

#pragma once
#define SIZES_TABLE(OP)
OP(1) 
OP(2) 
OP(12)

foo.cpp

#include "valid_sizes.hpp"
// ...
#define INSTANTIATE(Size) template struct Foo<Size>;
SIZES_TABLE(INSTANTIATE)
#undef INSTANTIATE

您可以用辅助类递归实例化Foo类。不幸的是,您需要在构造函数中对Foo的每种方法提供调用(虽然不会调用该方法(,以便为链接提供定义:

// foo.cpp: 
template <size_t S>
struct recursive_helper {
  Foo<S> foo;
  recursive_helper<S-1> r_helper;
  recursive_helper() {
    foo.bar();
    foo.baz();
  }
};
template <>
struct recursive_helper<0> {
  Foo<0> foo;
  recursive_helper() {
    foo.bar();
    foo.baz();
  };
};

然后您实例化助手类: template struct recursive_helper<6>;