为什么is_constructible声明的东西是可构造的,当它不是? [英] Why does is_constructible claim something is constructible when it isn't?

查看:175
本文介绍了为什么is_constructible声明的东西是可构造的,当它不是?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

以下程序在使用GCC 4.7和clang 3.2编译时会生成1作为输出。

The following program, when compiled with either GCC 4.7 and clang 3.2, produces "1" as output.

#include <type_traits>

struct foo {
    template<typename T>
    foo(T) {
        static_assert(not std::is_same<int, T>(), "no ints please");
    }
};

#include <iostream>    
int main() {
    std::cout << std::is_constructible<foo, int>();
}

这很混乱。 foo 显然不能从 int 构造!如果我将 main 更改为以下内容,则两个编译器都会由于静态断言失败而拒绝它:

This is confusing. foo is quite clearly not constructible from int! If I change main to the following, both compilers reject it due to the static assertion failing:

int main() {
    foo(0);
}

两个编译器如何说是可构造的?

How come both compilers say it is constructible?

推荐答案

这是标准的说法(§20.9.5/ 6),我强调:

This is what the standard has to say (§20.9.5/6), with my emphasis:


给定以下函数原型:

Given the following function prototype:

template <class T>
typename add_rvalue_reference<T>::type create();

模板专用化的谓词条件
is_constructible < Args ...> 必须满足,如果且仅当变量定义之后的
在一些发明的
变量 t

the predicate condition for a template specialization is_constructible<T, Args...> shall be satisfied if and only if the following variable definition would be well-formed for some invented variable t:

T t(create<Args>()...);

[注意:这些标记从不解释为函数
声明。 ]

[ Note: These tokens are never interpreted as a function declaration. —end note ]

访问检查的执行方式与在 T
任何 Args 仅考虑
变量初始化的直接上下文的有效性。
注意:
初始化的评估可能会导致副作用作为
类模板特化和函数模板特化的实例化,
生成隐式定义的函数,等等。这种边
效果不在直接上下文,并且可能导致
程序不合格。 -end note ]

Access checking is performed as if in a context unrelated to T and any of the Args. Only the validity of the immediate context of the variable initialization is considered. [ Note: The evaluation of the initialization can result in side effects such as the instantiation of class template specializations and function template specializations, the generation of implicitly-defined functions, and so on. Such side effects are not in the "immediate context" and can result in the program being ill-formed. —end note ]

模板构造函数实例化时,断言失败。然而,如注释中所述,该断言不在所考虑的变量定义的直接上下文中,因此不影响其有效性。因此,编译器可以将该定义视为有效,因此声明 foo 确实可以从 int 构造,即使实际上尝试从 int 构造 foo 会导致错误的程序。

The assertion only fails when the template constructor is instantiated. However, as cleared up in the note, that assertion is not in the immediate context of the variable definition that is considered, and thus does not affect its "validity". So the compilers can count that definition as valid, and thus claim that foo is indeed constructible from int, even if actually attempting to construct a foo from an int results in an ill-formed program.

请注意,编译器也允许,而不是 is_constructible yield false,只是拒绝基于断言的原始程序,即使没有一个

Note that the compilers are also allowed to, instead of having is_constructible yield false, just reject the original program based on the assertion, even though neither one does.

这篇关于为什么is_constructible声明的东西是可构造的,当它不是?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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