【发布时间】:2018-02-06 14:50:20
【问题描述】:
代码
以下代码给出不同的输出,带有和不带有* 注释的行:
#include <iostream>
#include <type_traits>
template <bool>
using bool_void_t = void;
template <typename, typename = void>
struct is_complete : std::false_type
{
};
template <typename T>
struct is_complete<T, bool_void_t<sizeof(T) == sizeof(T)>> : std::true_type
{
};
template <typename Derived>
struct Base
{
static constexpr bool value = is_complete<Derived>{};
// using magic = bool_void_t<value>; // *
};
struct Foo : Base<Foo>
{
};
int main()
{
std::cout << std::boolalpha << Foo::value << std::endl;
}
输出
编译器及其标志
在这两种情况下,clang++ 5.0.0 都用作编译器,编译器标志为 -std=c++17 -Wall -Wextra -Werror -pedantic-errors。
更高级的研究
-
clang++ 5.0.0 (
-Wall -Wextra -Werror -pedantic-errors)-std=c++14 -std=c++17 * is commented false true * is not commented false false -
g++ 7.2.1 (
-Wall -Wextra -Werror -pedantic-errors)-std=c++14 -std=c++17 * is commented true true * is not commented false false
问题
- 编译器的这种行为是否符合标准?如果是,其背后的理由是什么?
- 当用
*标记的行被注释时(输出为@ 987654336@ 带有-std=c++14编译器标志和true带有-std=c++17一个)?
【问题讨论】:
-
我认为
is_complete的格式不正确......它的值可能取决于它的实例化位置。 -
@Jarod42 但是
magic类型别名会如何影响这一点(更改is_completeSFINAE 类的实例化点)? -
@constructor 我猜 using 声明会立即强制评估右侧。如果没有该声明,
value仅在访问时评估,当您访问Foo::value时。 -
一旦程序格式不正确(无需诊断),它类似于 UB,任何事情都可能发生。
-
From dependent_name "如果非依赖名称的含义在定义上下文和模板特化的实例化点之间发生变化,则程序格式错误,不需要诊断。这在以下情况下是可能的:在非依赖名称中使用的类型在定义时不完整,但在实例化时完整”。
magic似乎就是这种情况。
标签: c++ templates sfinae crtp incomplete-type