【问题标题】:C++ Alias for list of template parameters模板参数列表的 C++ 别名
【发布时间】:2018-03-14 11:28:09
【问题描述】:

我有很多 C++ 类使用相同的模板参数列表

template<typename T, typename Index, typename Bool, typename Data, Index n_x, Index n_u, Index n_c, Index n_w>
class A {
   ...
};

template<typename T, typename Index, typename Bool, typename Data, Index n_x, Index n_u, Index n_c, Index n_w>
class B {
   ...
};

template<typename T, typename Index, typename Bool, typename Data, Index n_x, Index n_u, Index n_c, Index n_w>
class C {
   ...
};

你明白了。然后我像

一样实例化它们
A<T, Index, Bool, Data, n_x, n_u, n_c, n_w> a;
B<T, Index, Bool, Data, n_x, n_u, n_c, n_w> b;
C<T, Index, Bool, Data, n_x, n_u, n_c, n_w> c;

有没有办法以某种方式为这组模板参数创建一个别名,这样我就不必不断重新输入参数列表?

我有这样的想法......

using Params = T, Index, Bool, Data, n_x, n_u, n_c, n_w;
A<Params> a;
B<Params> b;
C<Params> c;

我意识到我可以创建一个单独的类来定义类型并使用它。但我想知道是否有一种方法可以在不定义新类的情况下做到这一点。

编辑

我不想使用宏。

我也不想使用默认值,因为这需要确保默认值在一堆文件中是统一的。我意识到我可以定义一个新的默认标头并将其包含在所有文件中,但这似乎是糟糕的编程。

【问题讨论】:

  • 使用默认参数
  • 创建宏...
  • 我不想使用默认值,因为那样我就必须在每个文件中定义默认值。
  • 如果您需要类似的东西,那么我认为设计或该设计的实现存在缺陷。
  • @bremen_matt 你想要什么是不可能的。唯一的方法是将其专门用于类型列表。

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


【解决方案1】:

不完全是你问的,但没有那么不同......

但需要一些工作。

您可以使用带有双层模板管理的结构foo 来解决。

template <typename T, typename Index, typename Bool, typename Data,
          Index I1, Index I2, Index I3, Index I4>
struct foo
 { 
   template <template <typename, typename X, typename, typename, X, X, X, X>
                       class Cont>
   using type = Cont<T, Index, Bool, Data, I1, I2, I3, I4>;
 };

第一层,即结构层,包含您要修复的类型/值(在您的示例中为T, Index, Bool, Data, n_x, n_u, n_c, n_w)。

第二层,using 层,带有可变模板元素(ABC,在您的示例中。

你也可以添加一个using别名foot_t来简化使用

template <template <typename, typename X, typename, typename, X, X, X, X>
                    class Cont, typename C>
using foo_t = typename C::template type<Cont>;

现在您可以使用using 修复类型和值(第一层)

using f = foo<T, Index, Bool, Data, n_x, n_u, n_c, n_w>;

并使用foo_t声明激活第二层的变量

foo_t<A, f> a;
foo_t<B, f> b;
foo_t<C, f> c;

以下是一个完整的工作示例

#include <vector>
#include <iostream>

template <typename T, typename Index, typename Bool, typename Data,
          Index n_x, Index n_u, Index n_c, Index n_w>
class A { };

template <typename T, typename Index, typename Bool, typename Data,
          Index n_x, Index n_u, Index n_c, Index n_w>
class B { };

template <typename T, typename Index, typename Bool, typename Data,
          Index n_x, Index n_u, Index n_c, Index n_w>
class C { };

template <typename T, typename Index, typename Bool, typename Data,
          Index I1, Index I2, Index I3, Index I4>
struct foo
 { 
   template <template <typename, typename X, typename, typename, X, X, X, X>
                       class Cont>
   using type = Cont<T, Index, Bool, Data, I1, I2, I3, I4>;
 };

template <template <typename, typename X, typename, typename, X, X, X, X>
                    class Cont, typename C>
using foo_t = typename C::template type<Cont>;


int main ()
 {
   using T     = float;
   using Index = std::size_t;
   using Bool  = bool;
   using Data  = std::vector<std::string>;

   constexpr std::size_t n_x { 0U };
   constexpr std::size_t n_u { 1U };
   constexpr std::size_t n_c { 2U };
   constexpr std::size_t n_w { 3U };

   using f = foo<T, Index, Bool, Data, n_x, n_u, n_c, n_w>;

   foo_t<A, f> a;
   foo_t<B, f> b;
   foo_t<C, f> c;

   static_assert( std::is_same<decltype(a),
                     A<T, Index, Bool, Data, n_x, n_u, n_c, n_w>>{}, "!" );
   static_assert( std::is_same<decltype(b),
                     B<T, Index, Bool, Data, n_x, n_u, n_c, n_w>>{}, "!" );
   static_assert( std::is_same<decltype(c),
                     C<T, Index, Bool, Data, n_x, n_u, n_c, n_w>>{}, "!" );
 }

【讨论】:

  • 看起来不错。可能是最接近我的想法的一个。
  • 这段代码过于复杂。您只需要一个作曲家,它可以接受一个容器和一个类型,然后生成一个组合类型。 template&lt;class T, class Index, Index n_x, template&lt;class, class, Index&gt;class Container&gt; struct Composer { using type = Container&lt;T, Index, n_x&gt;; };template&lt;template&lt;class, class, size_t&gt;class Container&gt; using float_sizet_0_composer = typename Composer&lt;float, size_t, 0LU, Container&gt;::type;static_assert( std::is_same_v&lt;float_sizet_0_composer&lt;A&gt;, A&lt;float, size_t, 0LU&gt;&gt; );
  • @liliscent - 这样可以避免第二层......很好......但是(恕我直言)与我的解决方案有很大不同;我认为您应该将其作为替代答案。
【解决方案2】:

您可以用一个定义的、不完美但简单的解决方案替换别名,它可以工作。

#define PARAMS T, Index, Bool, Data, n_x, n_u, n_c, n_w
A<PARAMS> a;
B<PARAMS> b;
C<PARAMS> c;

注意:定义末尾没有;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-11-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-09
    • 2018-10-12
    相关资源
    最近更新 更多