【问题标题】:Structured template parameters结构化模板参数
【发布时间】:2021-01-22 15:24:40
【问题描述】:

建立在这个答案之上:

https://stackoverflow.com/a/3319851/13250135

我想将我的模板参数结构化为方案,因为在同一应用程序的不同上下文中使用相同的类。

// adapted from https://stackoverflow.com/a/3319851
template<typename _string, typename _real>
struct scheme{
    public:
    using string = _string;
    using real = _real;
};

using scheme1 = scheme<std::string_view, double>;
using scheme2 = scheme<std::string, float>;

template<class scheme>
class Test {
    scheme::string text;
    scheme::real value;
    std::array<int, 10> array{};
};

Test<scheme1> test1{};
Test<scheme2> test2{};

到目前为止一切顺利。但现在我需要一种本身就是参数的类型。例如,我想用潜在的替代方案对std::array&lt;T&gt; 进行同样的参数化。

编辑:添加更多信息。

我想实现这样的目标:

template<typename _string, typename _real, typename _collection>
struct scheme{
    public:
    using string = _string;
    using real = _real;
    using collection = _collection;
};

using scheme1 = scheme<std::string_view, double, std::array>;
using scheme2 = scheme<std::string, float, myNamespace::myArray>;

template<class scheme>
class Test {
    scheme::string text;
    scheme::real value;
    scheme::collection<int, 10> array{};
};

但这当然行不通,因为没有参数的std::array 不是有效的类型名。但是我需要能够仅在模板实例化的地方提供这些最终参数,例如在Test 类中。

我为什么想要这样的东西?

有些类既可用于constexpr 方案(显然是所有 const 数据),也可用于各种非 const 方案。例如,我可以将std::string_view 用于constexpr 方案,将std::string 用于非常量方案。

另一个示例可能是提供与在特定于版本的二进制数据方案中持久保存的数据的兼容性(将数据从 32 位迁移到 64 位,代码页到 Unicode 等)。较新版本的应用程序需要实现所有方案才能在升级后读取旧数据。

谢谢, 标记

【问题讨论】:

  • 我不清楚您要解决什么编程问题。您可能想edit您的帖子并添加更多详细信息。
  • 你到底想达到什么目的?可以添加额外的模板参数,这样就可以给Test添加参数,专门针对std::array
  • 你的scheme 可能有intstd::array&lt;int, 10&gt; 的类型,constexpr size_t10,甚至是template usingint, 10 代替std::array
  • 您需要如何以及在何处进行参数化?是Test 类需要多种列表,可能是相同大小的多种std::array?为什么当前模式不起作用?我想提供帮助,但我很难理解您真正需要什么。
  • template template 参数浮现在脑海中,但没有提供足够的信息来完全了解它是否是您需要的。

标签: c++ templates c++20


【解决方案1】:

您需要将_collection 设为模板模板参数。

template<typename _string, typename _real, template<typename, size_t> typename _collection>
struct scheme{
    public:
    using string = _string;
    using real = _real;
    // This is now a template type alias, i.e. "variable inside the scheme"
    template<typename T, size_t N>
    using collection = _collection<T, N>;
};

您的 Test 类如下所示:

template<class scheme>
class Test {
    scheme::string text;
    scheme::real value;
    // As collection is no longer a type, the additional template disambiguator is needed here...
    scheme::template collection<int, 10> array{};
};

请注意,此解决方案仅适用于与std::array 具有相同“签名”的模板,即一个类型参数后跟一个整数非类型参数。 std::vector 例如不起作用。 因此,根据myNamespace::myArray 的实际类型,此解决方案可能不适用于您的问题。

编辑:我意识到您在问题中添加了 c++20 标签。在这种情况下,您可以省略 Test 类中的三个 typenames。 直播代码here.

【讨论】:

  • 非常感谢,这太棒了。你能推荐一本关于这些事情的书吗?涵盖 C++20?
  • 很遗憾没有,我通过反复试验以痛苦的方式学会了它。
猜你喜欢
  • 1970-01-01
  • 2019-08-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多