2016-08-30 1 views
3

J'ai écrit le code suivant à infixes une classe templated:Un modèle de modèle peut-il être spécialisé pour les types fondamentaux comme les modèles standards?

template<template<typename...> class C, typename A, typename B> 
struct infix_t 
{ 
    typedef C<A, B> type; 
}; 

template<template<typename...> class C, class A> 
constexpr infix_t<C, A> operator<(A, infix_t<C>) 
{ 
    return {}; 
} 


template<template<typename...> class C, typename A, typename B> 
constexpr C<A, B> operator>(infix_t<C, A>, B) 
{ 
    return {}; 
} 

Cela me permet d'écrire a <same_as> bsame_as est de type infix_t<std::is_same>. Toutefois, si le type a ou b est un type fondamental, j'obtiens template template argument has different template parameters...; si j'essaie de redéclarer infix_t pour accepter les types fondamentaux, j'obtiens template argument ... must be a class template or alias template. Je pensais que les modèles sur les noms de types pourraient accepter les fondamentaux de toute façon. Est-ce parce que c'est un modèle de modèle, et que les règles sont différentes, ou est-ce que je me contente d'aborder ce problème?

+0

pourrait vous montrer par exemple d'appeler un code qui donne cette erreur? – TemplateRex

+1

Quel est le point de cette syntaxe bizarre? – Columbo

+0

En réalité, il n'est pas nécessaire d'appeler pour donner cette erreur - les erreurs se produisent lorsque j'essaie de spécialiser le modèle. Cependant, mon utilisation prévue est 'auto infixed = infix_t ' où 'other' est un template sur un typename et un fondamental, comme' std :: integral_constant'. –

Répondre

0

Pour développer et modifier la solution par @Yakk un peu, voici une version qui permet la compilation comparaison des types

#include <type_traits> 

template<template<class...> class Op, class... Args> 
struct infix {}; 

template<template<class...> class Op, class L> 
constexpr infix<Op, L> operator<(L, infix<Op>) 
{ return {}; } 


template<template<class...> class Op, class L, class R> 
constexpr Op<L, R> operator>(infix<Op, L>, R) 
{ return {}; } 

constexpr auto same_as = infix<std::is_same>{}; 

template<int N> 
constexpr auto int_c = std::integral_constant<int, N>::value; 

int main() 
{ 
    static_assert(int_c<0> <same_as> int_c<0>); 
    static_assert(!(int{} <same_as> char{})); 
} 

Live Example

2

Pour rendre votre compilation de code, il est assez facile:

template<template<class...> class C, class...Z> 
struct infix_t {}; 

template<template<class...> class C, class A> 
constexpr infix_t<C, A> operator<(A, infix_t<C>) 
{ return {}; } 


template<template<class...> class C, class A, class B> 
constexpr C<A, B> operator>(infix_t<C, A>, B) 
{ return {}; } 

live example.

Si vous voulez prendre std::integral_constant et appliquer cela, vous devez d'abord l'envelopper:

template<class T, class U> 
using bob = std::integral_constant<T, U{}>; 

maintenant bob est un integral_constant qui ne prend types. Il s'attend à ce que le second type code la valeur de la constante, et le premier le type.

Il s'agit de tortues tout le long, en ce que U est probablement lui-même une constante intégrale.

Il est impossible de prendre la valeur 7 et de générer une constante intégrale à partir d'une expression. Vous pouvez prendre le jeton 7_constant et générer std::integral_constant<int, 7>, mais c'est un problème différent.

+0

hmm, je pensais que l'OP voulait pouvoir dire int int' (ou style Boost.Hana '0_c 0_c') , pas '0 0'. Je ne vois pas comment faire le premier. Aussi, sans le type imbriqué, devrait probablement juste utiliser 'infix' au lieu de' infix_t' – TemplateRex

+1

@temp sûr. Ils pourraient 'tag tag ' tho. – Yakk