T是否必须是要在`std :: declval <T>`中使用的完整类型?


11

考虑以下示例(来自此处):

#include <type_traits>
#include <iostream>
template <typename U>
struct A {
};

struct B {
   template <typename F = int>
   A<F> f() { return A<F>{}; }

   using default_return_type = decltype(std::declval<B>().f());
};

int main()
{
    B::default_return_type x{};
    std::cout << std::is_same< B::default_return_type, A<int>>::value;
}

在gcc9.2上编译时没有错误,但gcc7.2和clang 10.0.0抱怨B未完成。lang的错误是:

prog.cc:11:58: error: member access into incomplete type 'B'
   using default_return_type = decltype(std::declval<B>().f());
                                                         ^
prog.cc:7:8: note: definition of 'B' is not complete until the closing '}'
struct B {
       ^
prog.cc:16:8: error: no type named 'default_return_type' in 'B'
    B::default_return_type x{};
    ~~~^
prog.cc:17:35: error: no member named 'default_return_type' in 'B'
    std::cout << std::is_same< B::default_return_type, A<int>>::value;
                               ~~~^

1
问题标题似乎与错误不符?在我看来,GCC似乎在抱怨.f()。这就说得通了; 不完整类型B没有成员f
MSalters

@MSalters我也这么认为,但是这里真正的问题是什么?我假设一旦您从中获得实例,std::declval类型是否完整就不再重要了(我想我是错的)
idclev 463035818

[expr.ref] / 2(C ++ 11)关于类成员访问的说法:“对于第一个选项(点),第一个表达式应具有完整的类类型”。并且B在中既不完整也不认为完整alias-declaration
语言律师,


1
@LanguageLawyer好的,那么我同意我的解释已关闭,并且自c ++ 11以来似乎有所改变,这使得在较新的标准中可以实现上述要求,但在c ++ 11中却没有。您介意写答案吗?
idclev 463035818

Answers:


9

错误的来源不是std::declval,但类成员访问权限不完整。

在2.5年前合并CWG1836 的决议之前,该标准要求在类成员访问表达式()中完成该类。[expr.ref] / 2在C ++ 11中E1.E2

对于第一个选项(点),第一个表达式应具有完整的类类型。

[expr.ref] / 2在C ++ 17中

对于第一个选项(点),第一个表达式应该是具有完整类类型的glvalue。

一个班级本身并不被认为是完整alias-declarationmember-specification
[class.mem] / 6在C ++ 17中

}class-specifier结束时,类被视为完全定义的对象类型([basic.types])(或完整类型)。在类成员规范内,该类在函数体,默认参数,noexcept-specifier和默认成员初始化程序(包括嵌套类中的此类)内被视为完整的。否则,在其自己的类成员规范内,它被视为不完整。


8

来自[declval]

备注:模板参数Tdeclval可能是一个不完整的类型。

自C ++ 11起就存在这种措辞(因此,编译器不可能符合较早的标准)


太棒了,这就是我想要的。似乎gcc
已将

@ formerlyknownas_463035818:我的第一个想法是T绝对应该是完整的类型。很高兴我检查了标准。
AndyG '19
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.