编译器可以决定忽略C++20仍然需要的依赖类型上缺失的类型名吗?

lf5gs5x2  于 2023-02-26  发布在  其他
关注(0)|答案(1)|浏览(134)

以下code使用MSVC编译,但由于依赖类型前缺少typename,因此使用GCC和Clang编译失败:

struct Foo { struct value{ }; };
struct Bar { int value; };

template<typename T>
constexpr size_t SIZE = sizeof(T::value); // missing typename here, for Foo

constexpr size_t s1 = SIZE<Foo>; // missing typename before dependent type above
constexpr size_t s2 = SIZE<Bar>;

MSVC方法不需要sizeof的typename,这看起来是合理的,因为sizeof对类型和变量都有效。另一方面,GCC和Clang看起来是照章办事,因为这是一种仍然需要typenameeven in C++20的情况,当上下文不能向编译器显示它是要满足类型还是变量时。
问题是这里是否允许MSVC是许可的,也就是说,如果编译器可以在没有typename的情况下正确地执行所需的操作,那么它是否被允许这样做?或者它是否与规范相矛盾?
MSVC与Clang和GCC的方法之间的差异体现在以下code中的实际差异上,code由所有三个编译器编译,但行为不同:

template<typename T> concept A1 = sizeof(typename T::value) > 0;
template<typename T> concept A2 = sizeof(T::value) > 0;

struct Foo { struct value{ }; };

constexpr bool v1 = A1<Foo>; // true with all
constexpr bool v2 = A2<Foo>; // true with MSVC, false with GCC and Clang

在上面的代码中,GCC和Clang认为A2中typename的省略是非法的,因此使概念失败,这不是编译错误,而是概念得到布尔值false([temp.constr.atomic])。
C++20规范([temp.res.general])列出了假定限定id是一个类型时不需要typename的地方。sizeof操作符不在该列表中,因此对于模板依赖类型,它似乎需要typename。另一方面,sizeof在示例中没有显示为 *ill-formed,对于缺少typename,不需要诊断 *(不在示例中并不说明什么,但在某种程度上仍然保留问题)。
为什么sizeof * 可以 * 允许推断正确的操作而不添加typename?主要是因为它不应该真正关心这是一个类型还是一个变量。并且规范没有明确指出这是一个格式错误。如果它确实指出这是一个格式错误,那么指向它的指针应该是答案,这可能会使MSVC行为成为一个缺陷。
顺便说一句,这并没有回答这个问题,我们可以让所有三个编译器都满意with the following code

template<typename T>
constexpr size_t SIZE = sizeof(T::value);

template<typename T> requires requires { typename T::value; }
constexpr size_t SIZE<T> = sizeof(typename T::value);

以及for the concept

template<typename T> concept A = 
            sizeof(T::value) > 0  ||
            sizeof(typename T::value) > 0;
uxhixvfz

uxhixvfz1#

标准在这一点上非常间接,但是很明显MSVC在这里不符合(在非SFINAE/concept的情况下,只允许发出一个警告(“sizeof的操作数被认为是一个类型,尽管缺少'typename'”)并继续,但这不是真正的要点。
请注意,即使在的平凡情况下

struct X;
int y=X;

错误在于X不能被解释为 unqualified-id,因为它没有被“适当地声明”([expr.prim.id.unqual]/1)。在模板中,语法解释由typename的存在或不存在来固定,尽管事实上 qualified-id 由此被产生而不知道它们的终端名称是否被如此适当地声明;如果最终发现它们在这方面有所欠缺,我们显然必须拒绝它们。

相关问题