2009-05-26 13 views
3

型とその型のオブジェクトを指定すると、型が整数かどうかに基づいて実際のオブジェクトにアクセスできるようにすることができます。私はこれを試したC++テンプレートの特殊化問題

template <typename T, T &N> 
struct C { 
    enum { Value = 0 }; 
}; 

template <int &N> 
struct C<int, N> { 
    enum { Value = N }; 
}; 

しかし、それは動作しません。私が似たようなことを達成できる方法はありますか?コンパイル時に起こる

編集私はこのようなものだった達成しようとしていた何

、:

if (type is int) { 
    return IntWrapper<int_value> 
else { 
    return type 
} 

あなたが実際にテンプレートのインスタンス内のオブジェクトへのポインタまたは参照を渡すことができ、そうであるように:

struct X { 
    static const int Value = 5; 
}; 

template <X *x> 
struct C { 
    static const int Value = (*x).Value; 
}; 

X x; 

std::cout << C<&x>::Value << std::endl; // prints 5 

しかし、明らかにこれらのすべてがテンプレートを初期化することですリングxの型、xもグローバルに宣言する必要があります。私がやろうとしていることに対しては使用しません。コンパイル時には結局は不可能だと思います。

+0

クラステンプレートでは、テンプレートタイプの引数を明示的に指定する必要があるため、関数テンプレートが必要なようです。あなたは何をしようとしているのかを明確にするための使用例を投稿できますか? –

+0

@j_random_hacker:テンプレートを空白のままにして、特殊なクラスを持つことができます...テンプレートタイプを指定する必要はありません。 – Partial

答えて

7

あなたがしようとしているのは、有効なC++テンプレートではありません。任意のオブジェクトをテンプレートパラメータとして使用することはできません。タイプ、整数リテラル、特定の特殊なケースの文字列リテラルで使用できます。他の記事へ

template<typename T, int val> 
struct Test 
{ 
    enum {Value = 0}; 
}; 

template <int val> 
struct Test<int, val> 
{ 
    enum {Value = val}; 
}; 




int main(int argc,char *argv[]) 
{ 
    int v = Test<int,1>::Value; 
} 
+0

そしてブール値も –

+0

なぜ誰かがあなたを落としてしまったのか分かりませんが、もう少しであなたを助けてくれることを願っています。 – Pieter

3

template <typename T> struct A 
{ 
    enum { Value = false }; 
}; 
template <> struct A<int> 
{ 
    enum { Value = true }; 
}; 

その他:

template<typename T, int val> 
struct Test { 
    static const int Value = 0; 
}; 

template <int val> 
struct Test<int, val> { 
    static const int Value = val; 
}; 


int main(int argc,char *argv[]) { 
    const int v = Test<int,1>::Value; 
} 
+0

これは機能しますが、整数であれば実際の値も必要です。 – drill3r

2

あなたはこのようにそれを行うことができます。これについてはどのように

3

を追加:あなたはenum {} -hackを使用する必要はありません


template <typename T> struct A 
{ 
    T value_; 
    A() : value() {} 
    enum { is_int = false }; 
}; 
template <> struct A<int> 
{ 
    int value_; 
    explicit A(int v) : value_(v) {} 
    enum { is_int = true }; 
}; 
0

あなたへの簡単な修正あなたが実際に引数をどこにも渡していないので、テンプレートの引数での参照を使用することは意味がありません。

+1

これは整数だけで動作します。フロートで試してみてください。 –

4

おそらく単純なオーバーロードされたテンプレートメソッドがあなたのケースで機能しますか?

template<typename T> 
void doSomething(const T& x) 
{ 
    // ... 
} 
void doSomething(int x) 
{ 
    // ... 
} 
2

Iは ができる一方 種類とその種類のオブジェクトを指定し、それは は、 型が整数であるか否かに基づいて決定を行うことができ、C++テンプレートを必要とします実際の オブジェクトにアクセスします。

型が整数であるかどうかに基づいて決定することができますが、どの型のオブジェクトでもテンプレートを宣言することができないという問題があります。だから型が整数であるかどうかを決める方法は疑問です。すべてのあなたの元のテンプレートに答える

注意がきちんとあなたの

template< typename T, T > 
class C {}; 

の代わりに

template < typename T, int > 
class C {}; 

に変更された。しかしC<int, 5>が完全に有効な宣言であるが、これは任意のためのケースではありませんタイプT、ケースC<float, 5.>のコンパイラエラーが発生します。

正確に達成しようとしていることを投稿できますか?

そして、第2のテンプレート引数は常にintで、あなたは、単に型が整数型である場合、その値を撮りたい、と0 otherwhise場合、レコードのために、あなたは、単に行うことができます。

#include <limits> 

template< typename T, int N > 
class C { 
    static const int Value = (std::numeric_limits<T>::is_integer) ? N : 0; 
}; 
0

AlexandrescuのModern C++ Designをチェックしてください。私は第2章があなたがしたいことの正しい例を持っていると信じています。

5

私があなたを誤解しない限り、あなたが望むものは不可能です。あなたの例では、ポインタテンプレートパラメータの無効な使用を示しています。

(*x).ValueValueを初期化することができるようにするための定数式でなければならないため、有効ではありません
template <X *x> 
struct C { 
    static const int Value = (*x).Value; 
}; 

。代わりにX::Valueとして使用すると、クラスX内のValueは定数式として問題ありません。しかし、今回は、ポインタが関係するためではありません(定数式でも参照は等しく無効です)。

Magic<T, someT>::type 

そしてTのみ列挙、整数、ポインタすることができるので、Tはそうでないint型、およびIntWrapper<someT>されていない場合::typeはTであることを期待:あなたがこれを行うことはできません、まとめると

または参照型。そして、後者の2つのケースでは、ポインタによって指されたものの値、または参照によって参照される値がのコンパイル時にになることはありません。 あなたがそれに満足していれば、あなたの問題を解決するのは簡単です。私はあなたにどのように(あなたはすでに知っていると思われますか)あなたを見せません。

私はあなたの問題を解決することが、与えられた規則では不可能になった状況に身動きしたと思います。問題を解決するには、いくつかの手順を実行して、解決しようとしている実際の問題を表示します。

0

Template specializationは、この(www.cplusplus.comから取られたコード)のように達成することができます:あなたのケースでは

// template specialization 
#include <iostream> 
using namespace std; 

// class template: 
template <class T> 
class mycontainer { 
    T element; 
    public: 
    mycontainer (T arg) {element=arg;} 
    T increase() {return ++element;} 
}; 

// class template specialization: 
template <> 
class mycontainer <char> { 
    char element; 
    public: 
    mycontainer (char arg) {element=arg;} 
    char uppercase() 
    { 
     if ((element>='a')&&(element<='z')) 
     element+='A'-'a'; 
     return element; 
    } 
}; 

int main() { 
    mycontainer<int> myint (7); 
    mycontainer<char> mychar ('j'); 
    cout << myint.increase() << endl; 
    cout << mychar.uppercase() << endl; 
    return 0; 
} 

あなたはクラステンプレートの特殊化で欲しいもので炭を交換する必要があります。さて、私はあなたが達成しようとしていることを本当に確信していませんが、上記の例がテンプレートの専門化をどのように行うことができるかを示す良い指標となることを願っています。私が達成しようとしていた何

0

たコンパイル時に起こるこのような何か、:

if (type is int) { 
    return IntWrapper<int_value> 
else { 
    return type 
} 

私はあなたがで開始するIntWrapperを使用していない理由はわかりません。 IntWrapperにコンパイル時の整数定数をラップする必要性はどこから来ましたか?

それ以外の場合は、実行時にしか利用できないデータでテンプレートをインスタンス化しようとしているようです。

関連する問題