gpt4 book ai didi

c++ - 类模板参数推导不适用于别名模板

转载 作者:太空狗 更新时间:2023-10-29 23:11:06 25 4
gpt4 key购买 nike

考虑下面粘贴的代码。我已经定义了一个非常简单的类,编译器为它生成了一个隐式推导指南,因此可以在没有显式模板参数的情况下构造它。但是,模板参数推导不适用于从仅直接转发到目标类的简单别名模板构造对象:

template< typename A, typename B >
struct Foo {
Foo( A const &a, B const &b )
: a_(a), b_(b)
{ }

A a_;
B b_;
};

template< typename A, typename B >
using Bar = Foo<A, B>;

auto foobar() {
Foo r{1, 2};
Bar s{3, 4};
// ../src/geo/vector_test_unit.cpp: In function 'auto foobar()':
// ../src/geo/vector_test_unit.cpp:16:6: error: missing template arguments before 's'
// Bar s{3, 4};
// ^
return 1;
}

正如您从上面的代码注释中看到的那样,g++ 给我一个关于使用不带模板参数的别名模板的错误。我希望在这种情况下能够转发模板参数推导。

那么,我的问题:这是对类模板参数推导提案的当前措辞的明确设计吗?或者这是该功能当前 g++ 实现中未完成的功能或错误?对于提案的作者或 C++ ISO 委员会来说,这更像是一个问题,但如果他们中的任何人看到这个: Would it was desired that the final wording of the feature include enabling alias templates such as this to also是否为他们生成了隐式指南?

我能理解,由于别名模板可以有任何类型的模板参数,编译器可能并不总是能够成功地推断出目标类模板参数,但在这种情况下,我希望编译器能够以与直接针对目标类相同的方式。

几天前,我正在使用 --std=c++1z 从 head 构建 gcc。完整的版本信息是:gcc version 7.0.0 20161201 (experimental) (Homebrew gcc HEAD- --with-jit)

最佳答案

这是我们在制定提案时考虑的功能,但最终从 C++17 功能集中删除,因为我们还没有足够好的设计。特别是,关于如何从别名模板选择推导指南并将其转换为别名模板的推导指南,存在一些微妙之处。如果别名模板不是另一个模板的简单别名,还有关于如何表现的悬而未决的问题。一些例子:

template<typename T> struct Q { Q(T); };     // #1
template<typename T> struct Q<T*> { Q(T); }; // #2
template<typename U> using QP = Q<U*>;
int *x;
Q p = x; // deduces Q<int*> using #1, ill-formed
QP q = x; // deduces Q<int*> using #1, or
// deduces Q<int**> using #2?

template<typename T> Q(T) -> Q<T>; // #3
QP r = x; // can we use deduction guide #3 here?

template<typename T> Q(T*) -> Q<T**>; // #4
int **y;
QP s = y; // can we use deduction guide #4 here?

template<typename T> struct A { typedef T type; struct Y {}; };
template<typename T> using X = typename A<T>::type;
template<typename T> using Y = typename A<T>::Y;
X x = 4; // can this deduce T == int?
Y y = A<int>::Y(); // can this deduce T == int?

上述问题有不错的答案,但解决这些问题会增加复杂性,而且似乎最好禁止推导 C++17 的别名模板,而不是仓促加入有缺陷的东西。

更新 [C++20]:该主题已针对 C++20 重新讨论,我们批准了 P1814R0 ,它允许对别名模板进行类模板参数推导。

原来的例子现在有效。对于上面的例子:

  • CTAD 仍然只考虑来自主模板的构造函数。所以在 QP q = x; ,不考虑#2,而是使用#1 的构造函数。该构造函数被隐式转换为 Q 的指南:

    template<typename T> Q(T) -> Q<T>;

    然后转换为别名模板的指南 QP通过推导出 Q 指南的右侧( Q<T> ) 来自别名模板 ( Q<U*> ) 的右侧,推导出 T = U* ,然后将其替换回指南中,从而产生等效于:

    template<typename U> Q(U*) -> Q<U*>;
    // ... which is effectively ...
    template<typename U> QP(U*) -> QP<U>;
    // ... except that explicit deduction guides are not
    // permitted for alias templates

    然后使用该指南推断 q 的类型, 推导出 U = int , 所以 q 的类型是Q<int*> , 所以 q 的初始化格式错误。

  • r的初始化确实考虑推导指南 #3,它被转换为 QP 的指南如上所述

  • s的初始化确实考虑演绎指南#4;推导 Q<T**>来自 Q<U*>什么都不推导,所以我们保留推导指南

    template<typename T> Q(T*) -> Q<T**>;

    照原样,但添加一个约束,即推导结果必须匹配 QP 的形式.然后我们推导出T = int ,将其代入以计算结果类型 Q<int**> ,并检查我们是否可以推断出 QP<U>来自 Q<int**> ,我们可以。所以 s 的类型推导为 Q<int**> .

  • 仅当别名模板的右侧是 simple-template-id(格式为 maybe::stuff::templatename<args>)时,才支持别名模板的 CTAD。所以 X 都不是也不Y是可推导的。

关于c++ - 类模板参数推导不适用于别名模板,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51999938/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com