L'utilisation de ceci et des attributs dans les types de retour de fonction des membres?

StackOverflow https://stackoverflow.com/questions/9018460

  •  14-11-2019
  •  | 
  •  

Question

Dans ce réponse J'ai donné, il était logique d'utiliser this Et l'attribut de la classe _arg dans le type de retour traîné dans le cadre du decltype expression. Il est possible de se passer, mais gênant.

Ni clang 3.0 (voir ci-dessous) ni GCC 4.5.2 L'accept cependant.

#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 dit:

$ 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 ... pas si génial.

Cependant, le support de C ++ 11 est au mieux hacky dans la plupart des compilateurs et je n'ai pas pu trouver de restrictions spécifiques mentionnées dans la norme (N3290).

Dans les commentaires, Xeo a suggéré que cela aurait pu être un défaut dans la norme ...

Alors, est-ce autorisé ou non?

Bonus: Et les versions plus récentes de Clang / GCC soutiennent-elles cela?

Était-ce utile?

La solution

J'ai mal soutenu. C'était un défaut à un moment donné, mais était finalement résolu et voté dans les FDIS.

§5.1.1 [expr.prim.general]

Si une déclaration déclare une fonction membre ou un modèle de fonction membre d'une classe X, l'expression this est un prvalue de type «pointeur vers CV-Qualifier-seq X”Entre le facultatif cv-qualifer-seq et la fin du définition de fonction, membre du membre, ou déclarant.

En tant que tel, Clang et GCC ne l'implémentent pas encore correctement.

struct X{
  // 'this' exists between the | markers
  void f() const volatile | {
  } |
  auto g() const volatile | -> void {
  } |
};

Autres conseils

Votre code est non valide C ++ 11, car la classe n'est pas considérée comme complète dans le type de retour d'une fonction membre. Vous ne pouvez accéder qu'à des membres qui ont été déclarés auparavant. Ainsi

class MyClass {
private:
  int _arg;

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);
  }
};

Modulo que, oui en utilisant this est valide dans C ++ 11 dans un type de retour après.

Je ne sais pas si ce que vous écrivez est légal, mais il existe d'autres façons de réaliser ce que vous voulez:

  template <typename F>
  auto apply(F& f) -> decltype(f(*(MyClass*)0, (int)0)) {
    return f(*this, _arg);
  }

Ou:

  template <typename F>
  typename std::result_of<F(MyClass,int)>::type apply(F& f) {
    return f(*this, _arg);
  }
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top