为什么is_constructible声明的东西是可构造的,当它不是? [英] Why does is_constructible claim something is constructible when it isn't?
问题描述
以下程序在使用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屋!