【问题标题】:Is this auto template deduction guide is correct?这个自动模板扣除指南是否正确?
【发布时间】:2020-11-30 11:13:32
【问题描述】:

我正在学习自动模板推导指南:https://en.cppreference.com/w/cpp/language/class_template_argument_deduction。所以我想试试这个。

我有以下嵌套类结构,其中MyClass 是一个带有非模板参数的模板类,而内部结构MyStruct 只是有一个std::array<int, N>

我有MyStruct mStruct; 会员:

#include <iostream>
#include <array>

template<size_t N>
class MyClass
{
public:
   struct MyStruct
   {
      using ArrayType = std::array<int, N>;
      ArrayType arr;
   };
   MyStruct mStruct;

   MyClass(typename MyStruct::ArrayType const& arr)
      : mStruct{ arr }
   {}
};
// deduction guid
template<size_t N>
MyClass(typename MyClass<N>::MyStruct::ArrayType)->MyClass<N>;

我想像这样实现或构建 MyClass

 MyClass myObj{ typename MyClass<2>::MyStruct::ArrayType{ 1, 2} };

因此我给出了上述的扣除指南。

此代码在 MSVC 2019 中运行:https://godbolt.org/z/7PzzbM

然后想看看其他 GCC 和 Clang 的编译器。但他们不接受我的代码:https://godbolt.org/z/M8cPKj

错误:

source > : In function 'int main()' :
   <source> : 25 : 67 : error : class template argument deduction failed :
25 | MyClass myObj{ typename MyClass<2>::MyStruct::ArrayType{ 1, 2} };
| ^
<source>:25 : 67 : error : no matching function for call to 'MyClass(MyClass<2>::MyStruct::ArrayType)'
< source > : 15 : 4 : note : candidate : 'template<long unsigned int N> MyClass(const typename MyClass<N>::MyStruct::ArrayType&)-> MyClass<N>'
15 | MyClass(typename MyStruct::ArrayType const& arr)
| ^ ~~~~~~
<source> : 15 : 4 : note : template argument deduction / substitution failed :
<source> : 25 : 67 : note : couldn't deduce template parameter 'N'
25 | MyClass myObj{ typename MyClass<2>::MyStruct::ArrayType{ 1, 2} };
| ^
<source>:5 : 7 : note : candidate : 'template<long unsigned int N> MyClass(MyClass<N>)-> MyClass<N>'
5 | class MyClass
| ^ ~~~~~~
<source> :5 : 7 : note : template argument deduction / substitution failed :
<source> : 25 : 67 : note : 'std::array<int, 2>' is not derived from 'MyClass<N>'
25 | MyClass myObj{ typename MyClass<2>::MyStruct::ArrayType{ 1, 2} };
| ^
<source>:21 : 1 : note : candidate : 'template<long unsigned int N> MyClass(typename MyClass<N>::MyStruct::ArrayType)-> MyClass<N>'
21 | MyClass(typename MyClass<N>::MyStruct::ArrayType)->MyClass<N>;
| ^ ~~~~~~
<source>:21 : 1 : note : template argument deduction / substitution failed :
<source> : 25 : 67 : note : couldn't deduce template parameter 'N'
25 | MyClass myObj{ typename MyClass<2>::MyStruct::ArrayType{ 1, 2} };
| ^
ASM generation compiler returned : 1
  • 我是否正确完成了扣除指南?
  • 哪个编译器是正确的?

真的很抱歉,如果这是我的一个愚蠢的错误,但是编译器;他们不应该表现得正确吗?

【问题讨论】:

  • 这似乎是一种奇怪的构造对象的方式。如果为构造函数指定参数,为什么还要有推导指南? MyClass myObj{ { 1, 2} }; 不是更有意义吗?
  • @cigien 是的,这就是想法:godbolt.org/z/5Pdvjv 但我在 MSVC 中遇到了错误:然后我虽然需要明确地告诉类型。
  • 不,想法是对的,只是演绎指南错了。我会发布一个答案。
  • 您的演绎指南包含一个参数,该参数是non-deduced context。它无法工作。
  • @StoryTeller-UnslanderMonica 你能详细说明一下吗?为什么 MSVC 仍然接受它?

标签: c++ templates c++17


【解决方案1】:

您可以编写一个推导指南,将大括号初始化器列表参数视为这样的数组:

template<size_t N>
MyClass(int const (&)[N]) -> MyClass<N>;

然后你可以这样构造一个对象:

MyClass myObj{ { 1, 2} };

这是demo

【讨论】:

  • 是的,...这比我想象的要简单得多。
  • 它也适用于msvc
  • 我还在想,为什么 mein 没有工作。 :(
  • 查看@StoryTeller 对您的问题的评论。 :: 左侧的所有内容都是非推断上下文。
  • 意思是我的方式,永远不可能?但是,即使是我的版本,MSVC 也接受它。
猜你喜欢
  • 2020-02-17
  • 1970-01-01
  • 1970-01-01
  • 2018-03-19
  • 2021-10-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-10-02
相关资源
最近更新 更多