【问题标题】:How to specify template deduction guides for template aliases?如何为模板别名指定模板推导指南?
【发布时间】:2024-04-30 22:55:02
【问题描述】:

我正在尝试使用/std:c++17VS 2019 (16.10.4) 中编译此代码。以下失败:

namespace my
{
   template<class _Key, class _Compare = std::less<_Key>, class _Allocator = std::allocator<_Key>>
   using Set = std::set<_Key, _Compare, _Allocator>;
}

void test()
{
    std::set set1 = { 1, 2, 3 };
    static_assert(std::is_same_v<std::set<int>, decltype(set1)>);

    my::Set set2 = { 1, 2, 3 }; // Error here.
    static_assert(std::is_same_v<my::Set<int>, decltype(set2)>);
}

有错误:

error C2955: 'my::Set': use of alias template requires template argument list
message : see declaration of 'my::Set'

相同的代码在没有任何推导指南的情况下使用gcc -std=c++17 在 Godbolt 上编译得很好。见sample

有没有办法在VS 2019 (16.10.4)/std:c++17 上进行编译?我的实际代码非常冗长。我创建了这个最小的可重现样本,它可能只是为了解决这个小问题。我也尝试为my::Set 指定deduction guides,但它们有类似的错误。

【问题讨论】:

  • clang 的类似错误:alias template 'Set' requires template arguments; argument deduction only allowed for class templates"Alias templates are never deduced" - en.cppreference.com/w/cpp/language/template_argument_deduction。不知道为什么 gcc 允许它。
  • “有没有办法在 VS 2019 上进行编译”...:看起来 GCC 有问题。将Set 设为一个类将适用于clang 和MSVS:gcc.godbolt.org/z/vTr4sedx4
  • 你不应该这样做,因为它使代码更难理解,因为几乎每个人都知道std::set是什么,但只有你知道my::Set。如果你想要别名,那么它应该是针对特定情况的。此外,拥有一组浮点数不是一个好主意,因为您很容易因为舍入问题而遇到问题。
  • 它与gcc9.4 出现相同的错误。使用VS (16.11) /std:c++20 构建正常
  • 模板别名的推导指南是 C++20 的一项功能。 More details in this answer.

标签: c++ c++17 visual-studio-2019 template-argument-deduction


【解决方案1】:

你代码中的my::Set是一个别名模板,别名模板的类模板参数推导是C++20的一个新特性:https://en.cppreference.com/w/cpp/compiler_support/20

实验可以发现,本例中的模板参数推导在Visual Studio 16.11 版本后可用,请同时指定/std:c++20 命令行选项。演示:https://gcc.godbolt.org/z/93jdvfPcn

使用 gcc -std=c++17 在 Godbolt 上,相同的代码可以正常编译,无需任何推导指南。

GCC 的一个 bug 是允许在 C++17 模式下对别名模板进行类模板参数推导:https://gcc.gnu.org/bugzilla/show_bug.cgi?id=103852

【讨论】: