应该通过类模板专业化推导来考虑推导指导参数的初始化吗? [英] Should deduction guide argument initialization considered by class template specialization deduction?

查看:80
本文介绍了应该通过类模板专业化推导来考虑推导指导参数的初始化吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

作为此问题的后续措施,我测试了clang和gcc的行为.看来这两个编译器对c ++标准有不同的解释.

As a follow up of this question, I tested the behavior of both clang and gcc. It appears that the two compiler have a different interpretation of the c++ standard.

在下面的示例中,如果需要根据推论指南假设的构造函数自变量复制不可复制的自变量,则GCC拒绝编译. Clang不执行此检查:

In the example below, GCC refuses to compile, if a non copyable argument would need to be copied according to the deduction guide hypothetical constructor argument. Clang does not perform this check:

#include <cstddef>

struct not_copyable{
    not_copyable()=default;
    not_copyable(const not_copyable&)=delete;
};
struct movable{
    movable()=default;
    movable(movable&&);
};

template <typename T, size_t N>
struct A
 { template <typename ... Ts> A (Ts const & ...) {} };

template <typename T, size_t N>
struct B
 { template <typename ... Ts> B (const Ts & ...) {} };

template <typename T, typename ... Ts>
A(T const &, Ts const & ...) -> A<T, 1U + sizeof...(Ts)>;

template <typename T, typename ... Ts>
B(T, Ts ...) -> B<T, 1 + sizeof...(Ts)>;


int main()
 {
   not_copyable nc;
   movable m;

   auto a0 = A{nc};    // gcc & clang -> compile
   auto a1 = A{m};     // gcc & clang -> compile
   auto b0 = B{nc};    // clang ->compile;  gcc -> error
   auto b1 = B{m};     // clang ->compile;  gcc -> error
 }

在C ++标准的本段中,定义了正确的行为 [over.match.class.deduct]/2 :

In think the right behavior is defined in this paragraph of the C++ standard [over.match.class.deduct]/2:

初始化和重载解决方案按如下所述执行 [dcl.init]和[over.match.ctor],[over.match.copy]或 [over.match.list](根据初始化类型而定 对于假设的类类型的对象,其中 选定的功能和功能模板被认为是 该类类型的构造函数,用于形成重载 设置,[...]

Initialization and overload resolution are performed as described in [dcl.init] and [over.match.ctor], [over.match.copy], or [over.match.list] (as appropriate for the type of initialization performed) for an object of a hypothetical class type, where the selected functions and function templates are considered to be the constructors of that class type for the purpose of forming an overload set,[...]

我强调"是为了形成过载集",因为我认为这是clang和gcc分离的地方. Clang似乎没有检查推论指南假设的构造方法是否为可行函数 ,但gcc确实如此.哪个编译器是正确的?

I emphasized "for the purpose of forming an overload set" because I think this is where clang and gcc diverge. Clang does not seem to check if the deduction guide hypothetical constructor is a viable function, but gcc does. Which compiler is right?

推荐答案

Clang似乎没有检查推论指南假设的构造函数是否可行,但gcc可以.

Clang does not seem to check if the deduction guide hypothetical constructor is a viable function, but gcc does.

实际上,推导指南 是可行的功能.一个可行的函数仅表示参数数量匹配,约束均已满足,并且您可以为每个参数/参数对形成隐式转换序列.当我们检查ICS是否存在时, .best.ics]/2 :

Actually, the deduction guide is a viable function. A function being viable just means that the number of arguments matches, the constraints are satisfied, and you can form implicit conversion sequences for each parameter/argument pair. And when we're checking if an ICS exists, [over.best.ics]/2:

其他属性,例如生存期,存储类,对齐方式,参数的可访问性,参数是否为位字段,以及是否删除函数,都将被忽略.

Other properties, such as the lifetime, storage class, alignment, accessibility of the argument, whether the argument is a bit-field, and whether a function is deleted, are ignored.

删除功能不会使它不可行是非常重要的,因为重要的是它仍然可以成为最佳可行的候选者.这意味着删除not_copyable的副本构造函数的事实应该仅在我们实际调用它时才生效.

It's very important that deleting a function does not make it non-viable, because it's important that it can still end up being the best viable candidate. This means that the fact that not_copyable's copy constructor is deleted should only come into effect when we're actually invoking it.

例如,gcc和clang都拒绝该程序. #1可行的候选者,尽管已删除副本构造函数,它也是最佳可行的候选者:

For example, both gcc and clang reject this program. #1 is a viable candidate, and it's the best viable candidate, despite the deleted copy constructor:

struct NC {
    NC() = default;
    NC(NC const&) = delete;
    NC& operator=(NC const&) = delete;
};       

void foo(NC );                            // #1
template <typename T> void foo(T const&); // #2

int main() {
    NC nc;
    foo(nc);
}

但是,我们实际上从来没有调用用于推论的综合函数和函数模板.我们只是执行重载解析并选择最佳候选者-我们仅用来选择类类型,然后从头开始.实际上,我们绝对不应要求复制.

But we're never actually invoking the synthesized functions and function templates that we use for deduction. We're just performing overload resolution and selecting the best candidate - which we're only using to pick the class type, and then we start over. At no point should we actually require copying.

我认为这是gcc错误.提交了 86439 .

I think this is a gcc bug. Filed 86439.

这篇关于应该通过类模板专业化推导来考虑推导指导参数的初始化吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆