类内朋友函数的返回类型扣除 [英] Return type deduction for in-class friend functions
问题描述
这里是一个小小的实验, 返回类型扣除 (在这两种情况下使用Clang 3.4 SVN和g ++ 4.8.1, std = c ++ 1y
)已在链接的工作文件中记录
#include< iostream&
struct A
{
int a_;
friend auto operator ==(A const& L,A const& R)
{
return L.a_ == R.a_; // a_的类型为int,所以应该返回bool
}
};
template< class T>
struct B
{
int b_;
friend auto operator ==(B const& L,B const& R)
{
return L.b_ == R.b_; // b_的类型为int,所以应该返回bool
}
};
使用BI = B< int> ;;
int main()
{
std :: cout< (A {1} == A {2})< \\\
; // OK for Clang,ERROR for g ++
std :: cout<< (BI {1} == BI {2})< \\\
; // Clang和g ++的错误
}
实例 。
问题:是在C ++ 14支持的类中友好函数的自动返回类型推导?
答案:我们正在处理 n3638 此处,
2。是否允许写`auto func();`,即不是定义的声明?
[dcl.spec.auto] / 1说
>
auto
和decltype(auto)
类型说明符指定稍后将替换的占位符类型,通过从初始化器中扣除或通过使用 trailing-return-type
和/ 2
如果声明的返回类型的函数包含一个占位符类型,函数的返回类型从函数体中的
return
语句(如果有)中推导出来。
虽然不是显式地允许声明如auto f();
对于函数(即没有定义的声明),从n3638和[dcl.spec.auto] / 11中可以清楚地看到它是允许的,而不是明确禁止的。
3。关于朋友函数呢?
到目前为止,示例
struct A
{
int a_;
friend auto operator ==(A const& L,A const& R);
}
auto operator ==(A& L,A const& R)
{return L.a_ == R.a_; }
应格式良好。现在有趣的部分是
A
定义中的friend函数的定义,即struct A
{
int a_;
friend auto operator ==(A const& L,A const& R)
{return L.a_ == R.a_; } // allowed?
}
在我看来,它是允许的。为了支持这一点,我将引用名称查找。在friend函数声明中定义的函数的定义中的名称查找跟在根据[basic.lookup.unqual] / 9的成员函数的名称查找之后。 / 8的同一部分指定在成员函数体内使用的名称的非限定查找。名称可以被声明为使用的方式之一是它将是
X
类的成员,或者是X
(10.2)。这允许广为人知的struct X
{
void foo(){m = 42; }
int m;
};
请注意
m
它在foo
中的使用,但它是X
的成员。
由此,我得出结论,即使
struct X
{
auto foo return m; }
int m;
}
这由clang ++ 3.4 trunk 192325支持。
名称查找需要在struct
完成后解释此函数,还要考虑:struct X
{
auto foo(){return X() }
X()= delete;
};
类似地,类中定义的友元函数主体只能在类完成时解释。
4。关于模板?
具体来说,
friend auto some_function(B const& L){return L.b_; } c>
首先, inject-class-name
B
等效于B
,参见[temp.local] / 1。它指的是当前的实例化([temp.dep.type] / 1)。
>
L.b _
是指当前实例化(/ 4)的成员。它也是当前实例化的依赖成员 - 这是在C ++ 11之后添加的,参见 DR1471 ,我不知道该怎么想:[temp.dep.expr] / 5说明这个 id-expression 是不是类型依赖的,并且据我所见[temp.dep.constexpr]没有说它是依赖于值。
如果
L.b _
中的名称不相关,则名称查找将遵循[temp.nondep]的通用名称查找规则。否则,这将是有趣的(依赖名称查找不是很好地指定),但考虑template< class T&
struct A
{
int foo(){return m; }
int m;
};
也被大多数编译器接受,我认为版本
auto
也应该有效。
在[temp.friend]中还有一个关于模板朋友的部分,
另请参阅 isocpp论坛中的高度相关的讨论。
Here is a little experiment with return type deduction for in-class friend functions (using Clang 3.4 SVN and g++ 4.8.1 with
std=c++1y
in both cases) that is not documented in the linked working paper#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++ }
Question: is automatic return type deduction for in-class friend functions supported in C++14?
解决方案With respect to the other answers: We're dealing explicitly with n3638 here, and how it's incorporated in the recent drafts of C++1y.
I'm using 9514cc28 from the commitee's github repository, which incorporates some (minor) fixes/changes to n3638 already.
n3638 allows explicitly:
struct A { auto f(); // forward declaration }; auto A::f() { return 42; }
And, as we can infer from [dcl.spec.auto], where this feature is specified, even the following will be legal:
struct A { auto f(); // forward declaration }; A x; auto A::f() { return 42; } int main() { x.f(); }
(but more on this later)
This is fundamentally different from any trailing-return-type or dependent name lookup, as
auto f();
is a preliminary declaration, similar tostruct A;
. It needs to be completed later on, before it is used (before the return type is required).Additionally, the problems in the OP are related to internal compiler errors. The recent clang++3.4 trunk 192325 Debug+Asserts build fails to compile as an assertion fails while parsing the line
return L.b_ == R.b_;
. I have not checked with a recent version of g++ as of now.
Is the OP's example legal wrt to a n3638?
This is a bit tricky IMO. (I'm always referring to 9514cc28 in this section.)
1. Where is it allowed to use `auto`?
[dcl.spec.auto]
6 A program that uses
auto
ordecltype(auto)
in a context not explicitly allowed in this section is ill-formed.2 The placeholder type can appear with a function declarator in the decl-specifier-seq, type-specifier-seq, conversion-function-id, or trailing-return-type, in any context where such a declarator is valid.
/5 also defines some contexts, but they're irrelevant here.
Therefore,
auto func()
andauto operator@(..)
are generally allowed (this follows from the composition of a function declaration asT D
, whereT
is of the form decl-specifier-seq, andauto
is a type-specifier).
2. Is it allowed to write `auto func();`, i.e. a declaration that is not a definition?
[dcl.spec.auto]/1 says
The
auto
anddecltype(auto)
type-specifiers designate a placeholder type that will be replaced later, either by deduction from an initializer or by explicit specification with a trailing-return-type.and /2
If the declared return type of the function contains a placeholder type, the return type of the function is deduced from
return
statements in the body of the function, if any.Although it doesn't explicitly allow a declaration like
auto f();
for a function (that is, a declaration without definition), it is clear from n3638 and [dcl.spec.auto]/11 that it is intended to be allowed, and not explicitly forbidden.
3. What about friend functions?
So far, the example
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_; }
should be well-formed. The interesting part now is the definition of the friend function inside the definition of
A
, that isstruct A { int a_; friend auto operator==(A const& L, A const& R) { return L.a_ == R.a_; } // allowed? }
In my opinion, it is allowed. To support this, I'll cite name lookup. The name lookup inside the definition of functions defined in a friend function declaration follows the name lookup of member functions as per [basic.lookup.unqual]/9. /8 of the same section specifies unqualified lookup for names used inside member function bodies. One of the ways a name can be declared to be used is that it "shall be a member of class
X
or be a member of a base class ofX
(10.2)". This allows the widely knownstruct X { void foo() { m = 42; } int m; };
Note how
m
isn't declared before its use infoo
, but it's a member ofX
.From this, I conclude that even
struct X { auto foo() { return m; } int m; }
is allowed. This is supported by clang++3.4 trunk 192325. Name lookup requires to interpret this function only after the
struct
has been completed, also consider:struct X { auto foo() { return X(); } X() = delete; };
Similarly, the body of friend functions defined inside a class can only be interpreted once the class is complete.
4. What about templates?
Specifically, what about
friend auto some_function(B const& L) { return L.b_; }
?First, the injected-class-name
B
is equivalent toB<T>
, see [temp.local]/1. It refers to the current instantiation ([temp.dep.type]/1).The id-expression
L.b_
refers to a member of the current instantiation (/4). It is also a dependent member of the current instantiation -- this is an addition made after C++11, see DR1471, and I don't know what to think about it: [temp.dep.expr]/5 states this id-expression is not type-dependent, and as far as I see [temp.dep.constexpr] doesn't say it's value-dependent.If the name in
L.b_
was not dependent, name lookup would follow the "usual name lookup" rules per [temp.nondep]. Else, this'll be fun (dependent name lookup is not very well specified), but considering thattemplate<class T> struct A { int foo() { return m; } int m; };
is accepted by most compilers as well, I think the version with
auto
should be valid, too.There's also a section about friends of templates in [temp.friend], but IMO it doesn't shed light on the name lookup here.
Also see this highly relevant discussion in the isocpp-forum.
这篇关于类内朋友函数的返回类型扣除的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!