Ecco una possibile soluzione che "funziona" con GCC 5.2 e Clang 3.7.
Io uso Filip Roséen 's Constexpr Meta-Container con alcune lievi modifiche. Come T.C. sottolineato, questo potrebbe essere made ill-formed in futuro, quindi questa soluzione è totalmente irragionevole nel codice di produzione, ma per ora è abbastanza interessante. Non sono nemmeno sicuro se questo è conforme al 100% agli standard.
// This is our meta-container
using TypeMap = atch::meta_list<class A>;
// Get a unique integral number associated with the provided type
template <class T>
struct encode_type
{
using type = T;
// Push T into the container and store the pre-push size
//(requires slight change to Filip's code)
static constexpr std::size_t value = TypeMap::push<T>();
};
// Get the type uniquely associated with the provided value
template <std::size_t V>
struct decode_type
{
static constexpr std::size_t value = V;
// Get the type at index V
// (requires a small helper function addition)
using type = decltype(TypeMap::at<V>());
};
Le modifiche apportate ai codice originale:
template<class T, class H = meta_list, std::size_t Size = counter::value()>
static constexpr std::size_t push (
size_type = push_state<
typename H::template value<>::template push<T>::result
>()
) { return Size; }
I modified atch::meta_list::push
per restituire la dimensione del meta-contenitore prima la spinta. Ho usato un parametro template con un argomento predefinito per garantire che la dimensione sia calcolata prima della push.
template<size_type Idx, class H = meta_list>
static constexpr auto at() -> typename H::template value<>::template at<Idx>::result;
ho aggiunto una piccola funzione decltype
aiuto nella atch::meta_list
al fine di nascondere tutto quel nome pasticcio dipendente.
Alcuni codice di prova:
int main() {
std::array<int, 4> encoded {
encode_type<int>::value,
encode_type<double>::value,
encode_type<std::string>::value,
encode_type<float>::value
};
std::cout << "Encoding: ";
for (auto i : encoded) std::cout << i << ", ";
std::cout << std::endl;
std::array<std::type_index, 4> decoded {
typeid(decode_type<0>::type),
typeid(decode_type<1>::type),
typeid(decode_type<2>::type),
typeid(decode_type<3>::type),
};
std::cout << "Decoding: ";
for (auto i : decoded) std::cout << i.name() << ", ";
std::cout << std::endl;
}
Sia Clang e GCC vomitare un sacco di avvertimenti, ma entrambi "lavoro"!
Clang compiles, runs and outputs:
Codifica: 0, 1, 2, 3,
decodifica: I, D, NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE, f,
GCC compiles, runs and outputs:
Codifica: 0, 1, 2, 3,
decodifica: I, D, NSt7__cxx1112basic_stringIcSt11char_traitsIcESaIcEEE, f,
Forse sarebbe meglio con una fase di pre-processing ...
Perché lo vorrebbe, dal momento che in fase di compilazione hai ottenuto il tipo stesso? – 101010
Escludendo alcuni hack malvagi, non penso che il conteggio (o la generazione di altri interi unici) al momento della compilazione come questo sia possibile, * a meno che * non siate disposti a enumerare tutti i tipi per i quali dovrebbe funzionare ('tuple' , quindi utilizzare l'indice). –
melak47
Come ho sottolineato di seguito, la risposta è "no". Tuttavia, è probabile che tu stia chiedendo * più di quanto tu non abbia realmente bisogno *. Le probabilità sono che hai un'applicazione in mente, ed è proprio quello che vuoi provare. Ma non hai incluso la tua motivazione generale in quanto sopra. Sentiti libero di fare una domanda che include ciò che vuoi realmente fare in un'altra domanda! – Yakk