【问题标题】:How can I give two compatible names to a C++ class template with deduction guides?如何为带有演绎指南的 C++ 类模板提供两个兼容的名称?
【发布时间】:2021-11-19 08:12:16
【问题描述】:

如果我有一个广泛使用的名为 Foo 的类模板,我想将其重命名为 Bar 而不必以原子方式更新其所有用户,那么在 C++17 之前我可以简单地使用类型别名:

template <typename T>
class Bar {
 public:
  // Create a Bar from a T value.
  explicit Bar(T value);
};

// An older name for this class, for compatibility with callers that haven't
// yet been updated.
template <typename T>
using Foo = Bar<T>;

在大型分布式代码库中工作时,这非常有用。然而,从 C++17 开始,这似乎被类模板参数推导指南所打破。例如,如果此行存在:

template <typename T>
explicit Foo(T) -> Foo<T>;

那么在重命名类时,显而易见的事情就是将演绎指南中的Foos 更改为Bars:

template <typename T>
explicit Bar(T) -> Bar<T>;

但现在随机调用者中的表达式Foo(17) 曾经是合法的,但现在是错误的:

test.cc:42:21: error: alias template 'Foo' requires template arguments; argument deduction only allowed for class templates
  static_cast<void>(Foo(17));
                    ^
test.cc:34:1: note: template is declared here
using Foo = Bar<T>;
^

有没有什么简单和通用的方法可以以完全兼容的方式给一个具有演绎指导的类提供两个同时命名的名称?我能想到的最好的方法是在两个名称下定义该类的公共 API 两次,使用转换运算符,但这远非简单和通用。

【问题讨论】:

  • 如果您从新类派生旧类,您将免费获得一些转换。但是,如果您的 API 用户混合了 auto&amp;Foo&amp;,则没有完美的解决方案,这在旧代码库中是很有可能的。

标签: c++ c++17 ctad


【解决方案1】:

您是否尝试过定义宏?

#define Foo Bar;

(我个人觉得它与同一实现的多个名称混淆,但我不是你。)

抱歉,我目前无法测试,但我希望它有效!

【讨论】:

  • 说真的,不。这破坏了所有类型的东西。宏不遵守命名空间。
  • 我真的很惊讶我实际上没有考虑到这一点。该名称恰好足够独特,因此这可能不是一个可怕的想法,因为它是一个非常临时的hack。谢谢。
【解决方案2】:

你的问题正是P1814R0: Wording for Class Template Argument Deduction for Alias Templates 想解决,也就是说在C++20中,只需要为Bar添加推导引导,就可以使下面的程序格式正确:

template <typename T>
class Bar {
 public:
  // Create a Bar from a T value.
  explicit Bar(T value);
};

// An older name for this class, for compatibility with callers that haven't
// yet been updated.
template <typename T>
using Foo = Bar<T>;

template <typename T>
explicit Bar(T) -> Bar<T>;

int main() {
  Bar bar(42);
  Foo foo(42); // well-formed
}

Demo.

但由于是C++20的特性,目前C++17没有解决方案。

【讨论】:

  • 太棒了,谢谢!不幸的是,clang 还没有实现 P1814R0。 :-(
猜你喜欢
  • 2019-09-23
  • 2018-02-16
  • 1970-01-01
  • 2020-05-09
  • 2021-06-20
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 2019-08-04
相关资源
最近更新 更多