作为此的后续question https://stackoverflow.com/q/51235025/5632316,我测试了 clang 和 gcc 的行为。看来两个编译器对 C++ 标准有不同的解释。
在下面的示例中,如果需要根据推导指南假设构造函数参数复制不可复制的参数,GCC 将拒绝编译。 Clang 不执行此检查:
#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++ 标准的这一段中定义了正确的行为[超过.匹配.类别.扣除]/2 http://eel.is/c++draft/over.match.class.deduct#2:
初始化和重载决策的执行方式如下所述
[dcl.init] 和 [over.match.ctor]、[over.match.copy] 或
[over.match.list](适合初始化类型
执行)对于假设类类型的对象,其中
选定的函数和函数模板被认为是
该类类型的构造函数为了形成过载
放,[...]
我强调“为了形成过载集“因为我认为这就是 clang 和 gcc 的分歧之处。Clang 似乎没有检查推导指南假设构造函数是否是一个可行的功能 http://eel.is/c++draft/over.match.viable,但海湾合作委员会确实如此。哪个编译器是正确的?
Clang 似乎不会检查推导引导假设构造函数是否是可行的函数,但 gcc 会检查。
其实,推导指南is一个可行的功能。函数可行仅意味着参数数量匹配、满足约束,并且您可以为每个参数/参数对形成隐式转换序列。当我们检查 ICS 是否存在时,[超过最佳.ics]/2 http://eel.is/c++draft/over.best.ics#2.sentence-2:
其他属性,例如生命周期、存储类、对齐方式、参数的可访问性、参数是否为位字段,以及函数是否被删除,被忽略。
删除一个函数不会使其变得不可行,这一点非常重要,因为重要的是它最终仍然可以成为最佳可行的候选函数。这意味着事实是not_copyable
的复制构造函数被删除应该只在我们实际调用它时才生效。
例如,gcc 和 clang 都拒绝该程序。#1
is a viable尽管删除了复制构造函数,但它是最佳可行的候选者:
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);
}
但我们实际上从来没有invoking我们用于推导的合成函数和函数模板。我们只是执行重载解析并选择最佳候选者 - 我们仅使用它来选择类类型,然后我们重新开始。我们在任何时候都不应该真正要求复制。
我认为这是一个 gcc 错误。提起86439 https://gcc.gnu.org/bugzilla/show_bug.cgi?id=86439.
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)