2

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

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

// 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;
    };

请注意,这个函数几乎有一半是 string 的重复<VertexID, EdgeMembershipType, SetBitmap>>,但是这个 string 的每次使用都适用于不同的类或函数,所以我不认为 alias 会起作用。

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

4

3 回答 3

5

比@Quentin 更具体的方法是让您的模板依赖于单个参数 - 预计该参数具有 VertexIDEdgeMembershipTypeSetBitmap.

// 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;
    };

请注意,当您想实际使用其中一种类型定义时,您将需要使用例如:typename Types::VertexID.

(理想情况下,您会想出一个比Types模板参数更好的名称。)

于 2017-01-10T16:05:49.257 回答
4

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

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

还有一个元函数,它用 a 中的内容实例化一个模板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>

在 Coliru 上现场观看

于 2017-01-10T15:55:50.053 回答
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例子演示了如何访问元组参数

希望这可以帮助

于 2017-01-10T16:06:00.343 回答