是否可以在C ++中“捆绑”模板参数?

时间:2017-01-10 15:44:59

标签: c++ c++11 templates using-declaration

有没有办法将模板参数“捆绑”在一起以避免重复?

我有几个类和函数都使用相同的三个模板参数。拥有一次使用每个类/函数的函数并不罕见。结果代码非常快速地变得非常混乱。 有没有更简洁的方法来编写这段代码?

// ContextFactory is a pointer to functions that instantiate objects that are subtypes of MetricContext
template<typename VertexID, typename EdgeMembershipType, typename SetBitmap>
using ContextFactory = MetricContext <VertexID, EdgeMembershipType, SetBitmap> *(*)(const char *);

template<typename VertexID, typename EdgeMembershipType, typename SetBitmap>
    static vector<ContextFactory<VertexID, EdgeMembershipType, SetBitmap>> buildCFList() {
      vector<ContextFactory<VertexID, EdgeMembershipType, SetBitmap>> answer;
      answer.push_back(MetricContext<VertexID, EdgeMembershipType, SetBitmap>::template make<NeoContext<VertexID, EdgeMembershipType, SetBitmap >>);
      return answer;
    };

请注意,此函数的近一半是字符串<VertexID, EdgeMembershipType, SetBitmap>>的重复,但每次使用此字符串都适用于不同的类或函数,因此我认为别名不起作用。

(如果有帮助,此函数的目的是创建一个指向函数的指针数组,这些函数将创建MetricContext<VertexID, EdgeMembershipType, SetBitmap>>

的子类型的对象

3 个答案:

答案 0 :(得分:5)

比@ Quentin更具体的方法是让你的模板依赖于一个参数 - 预计会有VertexIDEdgeMembershipTypeSetBitmap的typedef。

// ContextFactory is a pointer to functions that instantiate objects that are 
// subtypes of MetricContext
template<typename Types>
using ContextFactory = MetricContext <Types> *(*)(const char *);

template<typename Types>
    static vector<ContextFactory<Types>> buildCFList() {
      vector<ContextFactory<Types>> answer;
      answer.push_back(MetricContext<Types>::template make<NeoContext<Types>>);
      return answer;
    };

请注意,当您想要使用其中一个typedef时,您需要使用例如:typename Types::VertexID

(理想情况下,您会为模板参数提供比Types更好的名称。)

答案 1 :(得分:4)

是的,这是可能的。让我们定义一个小助手类来保存类型列表:

template <class... > struct pack { };

一个元函数,用pack中的内容实例化模板:

template <template <class... > class T, class P>
struct unpack_;

template <template <class... > class T, class... P>
struct unpack_<T, pack<P...>> {
    using type = T<P...>;
};

template <template <class... > class T, class P>
using unpack = typename unpack_<T, P>::type;

我们现在可以存储和使用我们的参数包:

template <class A, class B, class C>
struct Foo { };

using Params = pack<int, float, double>;

unpack<Foo, Params> f; // f is a Foo<int, float, double>

See it live on Coliru

答案 2 :(得分:1)

如果您正在使用C ++ 11,则可以使用std :: tuple将变量合并为一个。

理解相同的更简单的例子可以是

template <typename A, typename B, typename C>
void fn() {

 typedef std::tuple<A,B,C> myTuple;

  myTuple tpl;
  cout<<sizeof(std::get<0>(tpl))<<endl;;
  cout<<sizeof(std::get<1>(tpl))<<endl;
  cout<<sizeof(std::get<2>(tpl))<<endl;

}

int main() {

 fn<int,char,long>();

 return 0;
}

针对您的问题特有的问题,您可以创建元组的向量

template <typename A, typename B, typename C>
void fn() {

    using mycomb = std::tuple<A,B,C>;

    vector<mycomb> v1;
    v1.push_back(make_tuple(10,'c',20.0));
}

通过这种方式,您不需要重复相同的操作。元组getter函数起初有点尴尬。上面的cout示例演示了如何访问元组参数

希望这有帮助