忽略C ++中模板类的重复显式实例化

Sam*_*rsa 5 c++ templates c++03

如果我上课:

template <typename T>
class MyClass
{ 
 // ...
};
Run Code Online (Sandbox Code Playgroud)

我明确实例化了它:

template class MyClass<int>;
template class MyClass<int>; // second time
Run Code Online (Sandbox Code Playgroud)

我在某些编译器上遇到错误(例如Clang,但在VC ++ 2010上没有)。我为什么要这样做?好吧,在某些情况下T可能是typedef另一种类型。

template class MyClass<my_type_1>;
template class MyClass<my_type_2>;
Run Code Online (Sandbox Code Playgroud)

对于某些构建选项,my_type_1与相同my_type_2,在其他情况下则不同。我如何确保以上内容在所有情况下都能编译?有没有办法忽略重复的实例化?

Yak*_*ont 4

您可以找到另一种方法来显式实例化 ,template以便您可以对其进行元编程。

然后,不要每行执行一个实例化,而是将它们全部打包。对它们运行 n^2 算法(在编译时)以消除重复项(或者,老实说,您可能可以跳过它:根据您实例化模板的方式,它可能不在乎)。

像这样,假设Instantiate< Template, types< blah, foo, bar > >实际上实例化了作为第一个参数传入的模板上的列表:

#include <utility>
#include <type_traits>

template<typename T>
struct Test {};

template<typename... Ts>
struct types {};

template<template<typename>class Template, typename Types>
struct Instantiate {};

template<template<typename>class Template, typename T0, typename... Ts>
struct Instantiate<Template, types<T0, Ts...>>:
  Instantiate<Template, types<Ts...>>
{
  Template<T0>& unused();
};

template<typename U, typename Types>
struct prepend;

template<typename U, template<typename...>class pack, typename... Ts>
struct prepend< U, pack<Ts...> > {
  typedef pack<U, Ts...> types;
};
template<typename U, typename Types>
using Prepend = typename prepend<U, Types>::types;

template<typename U, typename Types, typename=void>
struct remove_type_from_types;
template<typename U, template<typename...>class pack>
struct remove_type_from_types<U, pack<>, void>
{
  typedef pack<> types;
};

template<typename U, template<typename...>class pack, typename T0, typename... Ts>
struct remove_type_from_types< U, pack<T0, Ts...>,
  typename std::enable_if< std::is_same<U, T0>::value >::type
>: remove_type_from_types< U, pack<Ts...> >
{};

template<typename U, template<typename...>class pack, typename T0, typename... Ts>
struct remove_type_from_types< U, pack<T0, Ts...>,
  typename std::enable_if< !std::is_same<U, T0>::value >::type
>
{
  typedef Prepend< T0, typename remove_type_from_types< U, pack<Ts...> >::types > types;
};

template<typename Types>
struct remove_duplicates {
  typedef Types types;
};

template<template<typename...>class pack, typename T0, typename... Ts>
struct remove_duplicates<pack<T0, Ts...>> {
private:
  typedef typename remove_type_from_types< T0, pack<Ts...> >::types filtered_tail;
  typedef typename remove_duplicates< filtered_tail >::types unique_tail;
public:
  typedef Prepend< T0, unique_tail > types;
};
template<typename Types>
using RemoveDuplicates = typename remove_duplicates<Types>::types;

static Instantiate<Test, RemoveDuplicates<types<int, double>> > unused;

int main() {

}
Run Code Online (Sandbox Code Playgroud)

如前所述,您可能可以取消整个消除重复位,因为我如何实例化template. 我也不确定上面对每个的使用是否template足以实例化它(即,它不会以某种方式被优化,并且符号将被导出)。

(递归深度在于n类型的数量,完成的总工作在于n^2类型的数量:我怀疑,对于任何合理数量的类型来说,递归深度足够浅且足够快。由于缺乏弱的弱功能,更高级的独特类型删除很困难订购裸体类型...)