In this answer I gave, it made sense to use this
and the attribute of the class _arg
in the trailing return type as part of the decltype
expression. It's possible to do without, but inconvenient.
Neither clang 3.0 (see below) nor gcc 4.5.2 accepted it though.
#include <iostream>
class MyClass {
public:
MyClass(int i): _arg(i) {}
template <typename F>
auto apply(F& f) -> decltype(f(_arg)) {
return f(_arg);
}
template <typename F>
auto apply(F& f) -> decltype(f(*this, _arg)) {
return f(*this, _arg);
}
private:
int _arg;
};
struct Id {
template <typename V>
V operator()(V v) const { return v; }
};
struct ComplexId {
template <typename C, typename V>
V operator()(C const&, V v) { return v + 1; }
};
int main() {
Id id; ComplexId complex;
MyClass c(0);
std::cout << c.apply(id) << " " << c.apply(complex) << "\n";
}
clang 3.0 says:
$ clang++ -std=c++11 -Weverything test.cpp
test.cpp:8:38: error: use of undeclared identifier '_arg'
auto apply(F& f) -> decltype(f(_arg)) {
^
test.cpp:8:45: error: type name requires a specifier or qualifier
auto apply(F& f) -> decltype(f(_arg)) {
^
test.cpp:8:45: error: C++ requires a type specifier for all declarations
auto apply(F& f) -> decltype(f(_arg)) {
~~~~~~~~ ^
test.cpp:8:7: error: 'auto' return without trailing return type
auto apply(F& f) -> decltype(f(_arg)) {
^
test.cpp:13:39: error: invalid use of 'this' outside of a nonstatic member function
auto apply(F& f) -> decltype(f(*this, _arg)) {
^
test.cpp:13:52: error: type name requires a specifier or qualifier
auto apply(F& f) -> decltype(f(*this, _arg)) {
^
test.cpp:13:52: error: C++ requires a type specifier for all declarations
auto apply(F& f) -> decltype(f(*this, _arg)) {
~~~~~~~~ ^
test.cpp:13:7: error: 'auto' return without trailing return type
auto apply(F& f) -> decltype(f(*this, _arg)) {
^
8 errors generated.
Hum... not so great.
However, the support of C++11 is hacky at best in most compilers and I could not find specific restrictions mentionned in the Standard (n3290).
In the comments, Xeo suggested that it might have been a defect in the Standard...
So, is this allowed or not ?
Bonus: and do more recent versions of clang / gcc support this ?
I misremembered. It was a defect at some point, but was eventually resolved and voted into the FDIS.
§5.1.1 [expr.prim.general]
If a declaration declares a member function or member function template of a class
X
, the expressionthis
is a prvalue of type “pointer to cv-qualifier-seqX
” between the optional cv-qualifer-seq and the end of the function-definition, member-declarator, or declarator.
As such, Clang and GCC just don't implement it correctly yet.
struct X{
// 'this' exists between the | markers
void f() const volatile | {
} |
auto g() const volatile | -> void {
} |
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With