我有一个带有大小模板化的类的库:
foo.hpp
:
template <size_t N>
struct Foo {
void bar();
};
Run Code Online (Sandbox Code Playgroud)
foo.cpp
:
template <size_t N>
void Foo<N>::bar() {
...
};
Run Code Online (Sandbox Code Playgroud)
我希望编译后的版本对于cpp文件中定义的特定大小列表无效。用伪代码,像这样
foo.cpp
:
template <size_t N>
void Foo<N>::bar() {
...
};
for (const auto & size: {1,2,7,9})
template struct Foo<size>;
Run Code Online (Sandbox Code Playgroud)
现在,我正在手动执行此操作(每种类型均无效),但这容易出错,因为我有多个文件应针对相同的大小进行定义。
我知道我可以将所有内容移动到头文件中,并使用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>();
Run Code Online (Sandbox Code Playgroud)
但我似乎无法正常工作。
您可以为此使用X宏方法:
valid_sizes.hpp
// Note: no include guards!!
PROCESS_SIZE(1)
PROCESS_SIZE(2)
PROCESS_SIZE(7)
PROCESS_SIZE(9)
#undef PROCESS_SIZE
Run Code Online (Sandbox Code Playgroud)
foo.cpp
// ...
#define PROCESS_SIZE(n) template struct Foo<n>;
#include "valid_sizes.hpp"
Run Code Online (Sandbox Code Playgroud)
bar.cpp
// ...
#define PROCESS_SIZE(n) some_other_use_of<n>;
#include "valid_sizes.hpp"
Run Code Online (Sandbox Code Playgroud)
或者,可以使用Boost.Preprocessor代替手动列表:
process_sizes.hpp
#pragma once
#define PROCESS_SIZES(macro, data) BOOST_PP_SEQ_FOR_EACH(macro, data, (1)(2)(7)(9))
Run Code Online (Sandbox Code Playgroud)
一些头文件
#define INSTANTIATE_CLASS(r, Name, size) template class Name<size>;
Run Code Online (Sandbox Code Playgroud)
foo.cpp
#include "process_sizes.hpp"
// ...
PROCESS_SIZES(INSTANTIATE_CLASS, Foo)
Run Code Online (Sandbox Code Playgroud)
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)
Run Code Online (Sandbox Code Playgroud)
请注意,显式实例化定义必须出现在名称空间范围内,因此不可能将它们放在您的tryd中instantiator
。
还要注意,隐式实例化(例如,在需要定义上下文的环境中引用类会导致这种隐式实例化)在翻译单元之外是“不可见的”,因此不能用作隐式实例化的替代。
换句话说,具有相同的大小列表会执行不同的操作,这需要为每次使用,使用宏或在C ++编译管道之外使用自定义代码生成来复制该列表。我认为宏是其中最简单,最可维护的。