Tem*_*Rex 30 c++ auto return-type-deduction c++14
这是一个关于类内朋友函数的返回类型推导的小实验(std=c++1y
在两种情况下都使用Clang 3.4 SVN和g ++ 4.8.1 ),链接工作文件中没有记录
#include <iostream>
struct A
{
int a_;
friend auto operator==(A const& L, A const& R)
{
return L.a_ == R.a_; // a_ is of type int, so should return bool
}
};
template<class T>
struct B
{
int b_;
friend auto operator==(B const& L, B const& R)
{
return L.b_ == R.b_; // b_ is of type int, so should return bool
}
};
using BI = B<int>;
int main()
{
std::cout << (A{1} == A{2}) << "\n"; // OK for Clang, ERROR for g++
std::cout << (BI{1} == BI{2}) << "\n"; // ERROR for both Clang and g++
}
Run Code Online (Sandbox Code Playgroud)
实例.
问题:C++ 14支持的类内朋友函数的自动返回类型推导?
dyp*_*dyp 11
关于其他答案:我们在这里明确地处理了n3638,以及它如何被包含在最近的C++ 1y草案中.
我正在使用来自commitee的github存储库的 9514cc28 ,它已经对n3638进行了一些(次要的)修复/更改.
n3638明确允许:
struct A {
auto f(); // forward declaration
};
auto A::f() { return 42; }
Run Code Online (Sandbox Code Playgroud)
而且,正如我们可以从[dcl.spec.auto]推断出指定此功能的地方,即使以下内容也是合法的:
struct A {
auto f(); // forward declaration
};
A x;
auto A::f() { return 42; }
int main() { x.f(); }
Run Code Online (Sandbox Code Playgroud)
(但稍后会详细介绍)
这与任何尾随返回类型或从属名称查找根本不同,auto f();
初步声明类似于struct A;
.它需要在使用之前(在需要返回类型之前)完成.
此外,OP中的问题与内部编译器错误有关.最近的clang ++ 3.4 trunk 192325 Debug + Asserts构建无法编译,因为断言在解析行时失败return L.b_ == R.b_;
.到目前为止,我还没有使用最新版本的g ++进行检查.
OP的例子是否合法到n3638?
这是一个有点棘手的IMO.(我在本节中总是指9514cc28.)
[dcl.spec.auto]
6 在本节中未明确允许使用
auto
或decltype(auto)
在其中使用的程序格式不正确.2 在这样的声明符有效的任何上下文中,占位符类型可以在decl-specifier-seq,type-specifier-seq,conversion-function-id或trailing-return-type中与函数声明符一起出现.
/ 5也定义了一些上下文,但它们在这里无关紧要.
因此,auto func()
和auto operator@(..)
通常都可以(从一个函数声明的组合物此为如下T D
,其中,T
具有以下形式DECL说明符-SEQ,并且auto
是一个类型说明符).
[dcl.spec.auto]/1说
的
auto
和decltype(auto)
类型说明符指定将以后,无论是通过从一个初始化扣除或通过用明确的规范被替换的占位符类型尾返回型.
和/ 2
如果函数的声明返回类型包含占位符类型,则函数的返回类型将从
return
函数体中的语句推导出来(如果有).
虽然它没有明确允许类似于auto f();
函数的声明(即没有定义的声明),但从n3638和[dcl.spec.auto]/11可以清楚地看出它是允许的,而不是明确禁止的.
到目前为止,这个例子
struct A
{
int a_;
friend auto operator==(A const& L, A const& R);
}
auto operator==(A const& L, A const& R)
{ return L.a_ == R.a_; }
Run Code Online (Sandbox Code Playgroud)
应该是格式良好的.现在有趣的部分是定义中定义的友元函数A
,即
struct A
{
int a_;
friend auto operator==(A const& L, A const& R)
{ return L.a_ == R.a_; } // allowed?
}
Run Code Online (Sandbox Code Playgroud)
在我看来,这是允许的.为了支持这一点,我将引用名称查找.在友元函数声明中定义的函数定义中的名称查找遵循[basic.lookup.unqual]/9的成员函数的名称查找.同一部分的/ 8指定对成员函数体内使用的名称进行非限定查找.可以声明使用名称的方式之一是它"应该是类X
的成员或者是X
(10.2)的基类的成员".这使得广为人知
struct X
{
void foo() { m = 42; }
int m;
};
Run Code Online (Sandbox Code Playgroud)
注意m
在使用foo
它之前是如何声明的,但是它是成员X
.
从这一点,我得出结论,甚至
struct X
{
auto foo() { return m; }
int m;
}
Run Code Online (Sandbox Code Playgroud)
被允许.这是由clang ++ 3.4 trunk 192325支持的.名称查找只需要struct
在完成后解释此函数,还要考虑:
struct X
{
auto foo() { return X(); }
X() = delete;
};
Run Code Online (Sandbox Code Playgroud)
类似地,只有在类完成后才能解释类中定义的友元函数体.
具体来说,怎么样friend auto some_function(B const& L) { return L.b_; }
?
首先,inject -class-name B
相当于B<T>
,参见[temp.local]/1.它指的是当前的实例化([temp.dep.type]/1).
所述ID-表达 L.b_
指的是当前实例的构件(/ 4).它也是当前实例化的依赖成员 - 这是在C++ 11之后添加的,参见DR1471,我不知道该怎么想:[temp.dep.expr]/5声明这个id -expression是没有类型相关,而据我见[temp.dep.constexpr]不说,它的价值依赖.
如果名称in L.b_
不依赖,则名称查找将遵循每个[temp.nondep]的"通常名称查找"规则.否则,这将是有趣的(依赖名称查找不是很好指定),但考虑到这一点
template<class T>
struct A
{
int foo() { return m; }
int m;
};
Run Code Online (Sandbox Code Playgroud)
也被大多数编译器所接受,我认为版本也auto
应该是有效的.
在[temp.friend]中还有一个关于模板朋友的部分,但IMO并没有说明这里的名字查找.
归档时间: |
|
查看次数: |
1820 次 |
最近记录: |