在C++中通过switch在运行时选择模板实例化方式

5

我有一组函数,它们都是由一个整数类型Index和一个类类型T模板化的。 我通过以下方式“部分专门化”:

// Integer type
enum Index{One,Two,Three,Four};

// Default implementation
template<int I>
struct Foo{
  template<typename T> static void bar(const T& x){ std::cout <<"default" << endl; }
};

// Template specializations
template<> 
struct Foo<One>{
  template<typename T> static void bar(const T& x){ std::cout << "one" << endl; }
};

我使用这个方法在程序运行时选择特定的索引,使用 switch 语句(这应该会产生一个高效的查找表)。这个 switch 不依赖于 T

template<typename T>
void barSwitch(int k, const T& x){
  switch(k){
    case ONE: Foo<ONE>::bar(x); break;
    case TWO: Foo<TWO>::bar(x); break;
    case THREE: Foo<THREE>::bar(x); break;
  }
}

这当然可以正常工作,但是类Foo并不是我想要应用switch的唯一类。实际上,我有很多类都是由相同的整数类型模板化的。因此,我希望能够将上面的barSwitch类与函数"Foo"一起“模板化”,以便我可以插入不同的类或不同的函数。我能想到的唯一方法是使用宏:

#define createBarSwitch(f,b) \
template<typename T> \
void barSwitch(int k, const T& x){ \
  switch(k){ \
    case ONE: f<ONE>::b(x); break; \
    case TWO: f<TWO>::b(x); break; \
    case THREE: f<THREE>::b(x); break; \
  }\
}

有没有更好的、更符合C++风格的方法来做到这一点?

如果您想通过一个函子类型进行参数化,请查看这里有关函子的讨论:https://dev59.com/dHRC5IYBdhLWcg3wROtQ - antlersoft
我相信你已经意识到函数不能进行部分特化,而是要完全特化“Foo”对象,但也许可以研究一下traits类或int-to-type惯用语法来选择所需的实例化。重载可能更简单。 - AJG85
我知道这并不是真正的部分特化。我只是指定了整数类型,但保持“T”类型未指定。 - Joel
2个回答

7

模板参数是关键:

enum Index { One, Two, Three, Four };

template <template <Index> class Switcher, typename T>
void barSwitch(int k, const T & x)
{
    switch (k)
    {
        case 1: Switcher<One>::template bar<T>(x); break;
        case 2: Switcher<Two>::template bar<T>(x); break;
        default: assert(false);
    }
}

使用方法:

template <Index I> struct Foo
{
    template <typename T> static void bar(const T & x);
};

barSwitch<Foo>(1, Blue);

(您需要确保替换为“Switcher”的每个可能模板都有一个成员模板“bar”,否则,您将会得到编译错误。)

0
template<template<int> class F>
struct BarFunc {};


template<>
struct BarFunc<Foo> {
    template<Index I, typename T>
    static void call(const T& x) {
        Foo<I>::bar(x);
    }
};


template<template<int> class F, typename T>
void barSwitch(int k, const T& x) {
    switch(k){
    case One: BarFunc<F>::call<One>(x); break;
    case Two: BarFunc<F>::call<Two>(x); break;
    case Three: BarFunc<F>::call<Three>(x); break;
    }
}

您可以通过提供BarFunc特化来参数化要调用的函数。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接