2017-07-21 3 views
1

Consultez le code suivant:Création d'un nouveau type à chaque instanciation en C++ 17

template <class /* Weird Hack Here */> 
struct object 
{ 
    constexpr object(int value, /* Other Weird Hack */) noexcept; 
}; 

int main() 
{ 
    object foo(1); 
    object bar(1); 
} 

Serait-il possible en utilisant des astuces étranges en C++ 17 et d'avoir foobar être différents types?

+3

Donc, si je mets x 'objet (1)' dans une boucle, attendez-vous un nombre illimité de différents types? – aschepler

+4

Quelque chose de similaire à ceci est probablement possible en raison de [metaprogramming stateful] (https://stackoverflow.com/q/44267673/1896169), mais sera interdit à l'avenir – Justin

+0

Pas C++ 17, mais la proposition metaclasses donnerait vous typedefs forte, qui accomplit presque la même chose. – AndyG

Répondre

6

Réelle réponse: Non. Si vous voulez des types différents, écrivez différents types. Le concept entier est fou.


Jouet réponse, bien sûr. D'une part, vous pourriez macro le type:

template <int N> 
struct object { 
    object(int) { } 
}; 

#define object object<__LINE__> 

Ou, puisque nous être insolent, vous pourriez macro sur les deux noms foo et bar:

template <int N> 
struct object { 
    object(int) { } 
}; 

#define foo(x) <0> foo(x) 
#define bar(x) <1> bar(x) 

Ou, peut-être juste un d'entre eux :

template <class T> 
struct object { 
    object(T) { } 
}; 

#define foo(x) <double> foo(x) 

Ou, vous pouvez utiliser stateful metaprogramming pour pirater des valeurs différentes. Cela fonctionne sur gcc mais pas sur clang:

template <int N> 
struct flag 
{ 
    friend constexpr int adl_flag(flag<N>); 
    constexpr operator int() { return N; } 
}; 

template <int N> 
struct write 
{ 
    friend constexpr int adl_flag(flag<N>) { return N; } 
    static constexpr int value = N; 
}; 

template <int N, int = adl_flag(flag<N>{})> 
constexpr int read(int, flag<N>, int R = read(0, flag<N + 1>{})) 
{ 
    return R; 
} 

template <int N> 
constexpr int read(float, flag<N>) 
{ 
    return N; 
} 

template <class T, int N=0, int R=write<read(0, flag<0>{})+N>::value> 
struct object { 
    object(T) { } 
};