C ++:实例化库中的许多模板

bre*_*att 5 c++ c++14

我有一个带有大小模板化的类的库:

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)

但我似乎无法正常工作。

Rei*_*ica 8

您可以为此使用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 ++编译管道之外使用自定义代码生成来复制该列表。我认为宏是其中最简单,最可维护的。

  • 这是对恕我直言的宏的有效使用,因为您要执行的操作是使用一些元语言来生成C ++代码...这就是预处理器的优点。 (3认同)
  • @bremen_matt-也不行。类模板的隐式实例化不会实例化其成员函数(模板),而仅实例化其声明。您必须使用成员函数(模板)。这很快就不再是有利的。您需要在此处使用显式实例化,并且只能使用宏来获取它。除了使用预处理器外,没有其他标准解决方案。 (3认同)