我有一个库,上面有一个尺寸的类:
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>;