Domanda

Ho scritto il seguente codice per ottenere l'offset di un elemento tupla

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

Questo è in realtà simile all'implementazione del offsetf macro. Sembra brutto, ma compila e funziona bene su 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;

stampe "1000".

Non so molto su Conmexpr, quindi le mie domande sono:

  1. È legale C ++?
  2. Ancora più importante, perché mi è permesso chiamare std :: get (che non è costexpr) all'interno di una funzione costexpr?

Per quanto ho compreso Contexpr, il compilatore è costretto a valutare il risultato dell'espressione al momento della compilazione, quindi non è possibile verificarsi alcuna dereferenziazione zero.

È stato utile?

Soluzione

È legale C ++?

Se per "legale" intendi "ben formato", allora sì.

Se per "legale" intendi "valido e lavorerà su qualsiasi compilatore e implementazione della libreria standard, allora no, perché std::tuple non è pod.

Perché mi è permesso chiamare std::get (che non è constexpr) all'interno di A. constexpr funzione?

Fondamentalmente, a constexpr La funzione non deve necessariamente consistere solo in un'espressione costante. Se hai provato a usare il tuo tuple_element_offset() Funzionare in un'espressione costante, otterresti un errore di compilazione.

L'idea è che una funzione potrebbe essere utilizzabile in un'espressione costante in alcune circostanze ma non in altre, quindi non c'è una restrizione che a constexpr La funzione deve essere sempre utilizzabile in un'espressione costante (poiché non esiste una tale restrizione, è anche possibile che un particolare constexpr La funzione potrebbe non essere mai utilizzabile in un'espressione costante, come nel caso della funzione).

La bozza C ++ 0x ha un buon esempio (da 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);
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top