2017-01-08 12 views
4

テンプレートをC++でテンプレートにしたい14。先験的には、打ち鳴らす++ V3.8でコンパイルしたときは、次のコードは、トリックにしかしテンプレートからC++へのテンプレートマップ14

template<class T> 
struct KeyType {}; 

template<class T> 
struct ValueType { 
    T x; 
}; 

template<template<class> class K> 
struct Map; 

template<> 
struct Map<KeyType> { 
    template<class T> 
    using type = ValueType<T>; 
}; 

ValueType<int> test{42}; 
Map<KeyType>::type<int> testM{42}; // Same as above 

、次の式を行うようだfalseを返します。

template<template<class> class TemplateType> 
struct NeedsTemplate; 

std::is_same< 
    NeedsTemplate<ValueType>, 
    NeedsTemplate<Map<KeyType>::type> 
>::value; // False 

私はそれがなぜ偽であるか理解します:it has already been answered here。基本的に、この標準では、エイリアスのテンプレートインスタンス化は同じものとして認識されるべきですが、テンプレート自体については何も言いません。したがって、g ++,std::is_sameが真であり、clang ++の場合はfalseです。

私の質問は、std::is_sameのg ++​​とclang ++の両方の要件を満たすテンプレートマップをテンプレートに実装するにはどうすればいいですか?私は最後の手段としてマクロを使用するつもりです...

答えて

1

テンプレートをメタプログラミングプリミティブとして使用しないでください。タイプを使用する。同様の、値を避ける。

template<template<class...>class Z> 
struct ztemplate{ 
    template<class...Ts> 
    using apply=Z<Ts...>; 
}; 
template<class Z, class...Ts> 
using apply=typename Z::template apply<Ts...>; 
using zapply=ztemplate<apply>; 

あなたがtemplate生の、ちょうどztemplate秒で動作することはありません。

template<class T> 
struct KeyType {}; 
using zKeyType=ztemplate<KeyType>; 

メタプログラミングは、種類によってはるかに良く動作します。あなたのタイプに制限があるようなら(それはztemplateでなければなりません)、それを強制するためにSFINAEまたは疑似概念を書いてください。

ボーナスとして、ztemplateは、テンプレートを定義するです。花型のメタプログラミングまであなたを開きます。

これは、テンプレートコードを標準的にラップし、テンプレートと値の直接のパラメータを削除する必要があることを意味します(それぞれztemplateと積分定数で置き換えます)。しかし、あなたはもっと強力なメタプログラミングに終わります。

X<Blah>の代わりにapply<zX, Blah>の代わりに。事実上、applyは、あなたが直接使用する唯一のテンプレートになります。

apply<zapply, zX, Blah>apply<zapply, zapply, zX, Blah>などは、apply<zX, Blah>と同じです。

+0

非常に興味深い、ありがとう。それはいくつかの仕事が必要ですが、それはそれが価値があるかもしれないと思います。私が理解していない何か:なぜあなたはタイプ「zapply」を導入していますか?例を提示するだけですか? – Kevin

+1

@Kevinさて、あなたは 'apply'自身でメタプログラムできるようにしたいのですが、あなたはテンプレートではなくタイプとしてそれを必要とします。 ;)たとえば、ztemplatesのリストとタイプのリストがあるとします。まず、2つのリストの相互積を生成します(2つの要素のリストのリストを生成します)。次に、クロスプロダクト要素またはそれ以上のものにfmapを適用します。 – Yakk

1

あなたが求めているのは、一般的に停止問題に相当する機能比較、つまり計算不可能な機能比較です。ただし、...

特定の定義済みのテンプレートでのみこれを行う場合は、タグクラス用に特殊化してから、タグクラスでNeedsTemplateを使用できます。つまり、

namespace Reflect { 
    struct Reflect {}; 
} 

template<class T> 
struct KeyType {}; 

namespace Reflect { 
    struct KeyType {}; 
} 

template<> 
struct KeyType<Reflect::Reflect> { 
    using type = Reflect::KeyType; 
}; 

です...そしてKeyType<Reflect::Reflect>で動作する、テンプレートである代わりにKeyTypeの種類、です。インターフェイス上でまだKeyType(テンプレート)を使用している可能性があります。反射の上でstd::is_same<>と呼ぶだけです。また、これは各タイプのリフレクションを書く必要がありますが、それはマクロでは些細なことですが。また、Reflect::Reflectをキータイプとして使用することはできません。 (あなたは特性を経由して、これに他の方法を行うことができますが、その後、複数のファイルと少しトリッキーです特質名前空間に特化している。)

#define REFLECT_TEMPLATE(TEMPL) \ 
    namespace Reflect {    \ 
     struct TEMPL {};    \ 
    };         \ 
    template<>       \ 
    struct TEMPL<Reflect::Reflect> { \ 
     using type = Reflect::KeyType; \ 
    }; 

私があなただったら、私も思います反射型にconst char* name() constを追加してください。

+0

非常に面白い、停止問題に平行して、おかげで! – Kevin

関連する問題