【问题标题】:Mixing aliases and template specializations混合别名和模板特化
【发布时间】:2019-05-03 11:52:57
【问题描述】:

我正在努力寻找最好的方法来拥有一种“对象”,它可以是专门的,也可以“链接”到另一种类型。

例如,您不能专门化一个类以使其成为简单的 int,并且您不能使用关键字 using 来专门化类。

我的解决方案如下:

template<class Category, Category code>
struct AImpl
  {};

template<class Category, Category code>
struct AHelper
  {
  using type = AImpl<Category, code>;
  };

template<class Category, Category code>
using A = typename AHelper<Category, code>::type;

template<int code>
void doSomething(A<int, code> object)
  {
  }

template<>
struct AImpl<int, 5>
  { 
  double a; 
  };

template<>
struct AImpl<int, 6>
  { 
  int b; 
  double c;
  };

template<>
struct AHelper<int, 7>
  {
  using type = int;
  };

template<class Category, Category code>
struct Alternative {};

template<int code>
void doSomethingAlternative(Alternative<int, code> object)
  {
  }

这可行,但您需要在 doSomething 中指定代码参数,我想避免这种情况。

例如:

A<int,7> a7; // This is equivalent to int
a7 = 4;
A<int, 5> a5; // This is equivalent to AImpl<int,5>
a5.a = 33.22;
doSomething(a5); // This does not compile
doSomething<5>(a5); // This compiles but is bulky
Alternative<int,0> alt0;
doSomethingAlternative(alt0); // This compiles and is not bulky
                              // but you're forced to use class
                              // specializations only

有没有办法实现我想要的?可以同时更改 doSomething 或 A 实现。

【问题讨论】:

  • 您的代码中没有模板特化。我不清楚这里的总体目标是什么超出了您展示的确切实现。我假设您希望以后能够换出AImpl,但不清楚您为什么不直接通过using A = AImpl1&lt;...&gt; 这样做。
  • 也就是说AHelper的意义何在?在您显示的代码中似乎没有必要,因此您能否扩展示例以包含 AHelper 部分的用途(这似乎是问题的核心)?
  • @MaxLanghof 没错,代码已更改。我希望现在更清楚了
  • 我添加了一些其他代码来向您展示替代方案。
  • 由于显而易见的原因,您省略了 doSomething 的实现,但是对于基本类型和类类型,它的工作方式完全相同的代码是什么?对于普通整数,在这样的函数中如何需要Category

标签: c++ c++11 templates template-meta-programming template-argument-deduction


【解决方案1】:

如果您尝试根据调用它的类型自定义doSomething 的行为,您不能让编译器从AHelpr::type 推导出东西(如之前的answered)。但是您可以通过以traits 的形式提供自定义点来告诉它它需要知道什么。例如:

template<typename T>
void doSomething(T& object)
{
    auto code = SmthTriats<T>::code;
}

鉴于SmthTriats 的专业化能力,这是高度可扩展的:

template<typename> struct SmthTriats;

template<typename Category, Category code_>
struct SmthTriats<AImpl<Category, code_>> {
    static constexpr auto code = code_;
};

template<>
struct SmthTriats<int> {
    static constexpr auto code = 7;
};

traits 类也允许在您的模块之外进行自定义。客户端代码只需要使用他们自己的类型专门化 SmthTriats,只要他们尊重你为你的 trait 制定的合同,你的代码就会为他们工作。

【讨论】:

  • 有趣,这也适用于 C++11 吗?不过,我认为这与我正在寻找的东西不同
  • @Saturnu - 当然。特征的概念几乎与 C++ 模板一样古老。标准库本身就大量使用它们。它们是提供有关类型(或类型族,在部分特化的情况下)的有趣属性的便捷方式。
  • 如果你想让你最初的尝试成功,我敦促你不要执着于一个解决方案。在您的代码库中尝试一下。这种技术是行业标准是有充分理由的。
  • @Saturnu - 这是另一种思考方式。 AHelper 确实是一个特征(映射到一个类型)。编译器不能假设映射是两种方式(如前所述)。你需要告诉它如何通过另一个特征反向映射。
  • @Saturnu - 我明白你的意思。是的,修复了这个特性。
猜你喜欢
  • 2017-01-20
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-24
相关资源
最近更新 更多