Question

J'ai écrit le code suivant pour obtenir le décalage d'un élément de tuple

template<size_t Idx,class T>
 constexpr size_t tuple_element_offset() {
        return static_cast<size_t>(
                    reinterpret_cast<char*>(&std::get<Idx>(*reinterpret_cast<T*>(0))) - reinterpret_cast<char*>(0));
    }

Ceci est en fait similaire à la mise en œuvre du offsetof macro. Il semble laid, mais compilera et fonctionne très bien sur gcc-4.6

typedef std::tuple<int,char,long> mytuple;

mytuple var = std::make_tuple(4,'c',1000);
char * ptr = reinterpret_cast<char*>(&var);
long * pt = reinterpret_cast<long*>(ptr+tuple_element_offset<2,mytuple>());

std::cout << *pt << std::endl;

affiche "1000".

Je ne sais pas trop constexpr, donc mes questions sont:

  1. Est-il légal c ++?
  2. Plus important encore, pourquoi je suis autorisé à appeler std :: get (qui est non constexpr) l'intérieur d'une fonction constexpr?

Pour autant que je comprends constexpr, le compilateur est obligé d'évaluer le résultat de l'expression au moment de la compilation, donc pas de boîte zéro dereferentiation se produit dans la pratique.

Était-ce utile?

La solution

Est-ce C ++ juridique?

Si vous voulez dire « bien formé » par « juridique » alors, oui.

Si par « légal » vous voulez dire « valide et fonctionne sur tous les compilateur et la mise en œuvre bibliothèque standard, puis, non, parce que std::tuple n'est pas POD.

Pourquoi je suis autorisé à appeler std::get (ce qui est constexpr) dans une fonction de constexpr?

En fait, une fonction constexpr ne doit pas nécessairement consister en juste une expression constante. Si vous avez essayé d'utiliser votre fonction tuple_element_offset() dans une expression constante, vous obtiendrez une erreur de compilation.

L'idée est qu'une fonction pourrait être utilisable dans une expression constante dans certaines circonstances, mais pas dans d'autres, donc il n'y a pas une restriction qu'une fonction constexpr doit toujours être utilisable dans une expression constante (car il n'y a pas une telle une restriction, il est également possible qu'une fonction constexpr particulière pourrait ne jamais être utilisable dans une expression constante, comme cela est le cas avec votre fonction).

Le projet de C ++ 0x a un bon exemple (de 5,19 / 2):

constexpr const int* addr(const int& ir) { return &ir; } // OK

// OK: (const int*)&(const int&)x is an address contant expression
static const int x = 5;
constexpr const int* xp = addr(x); 

// Error, initializer for constexpr variable not a constant expression; 
// (const int*)&(const int&)5 is not a constant expression because it takes
// the address of a temporary
constexpr const int* tp = addr(5);
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top