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グローバルに宣言する必要もあります。私がやろうとしていることは何の役にも立ちませんが、コンパイル時には結局不可能だと思います。

4

11 に答える 11

7

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

于 2009-05-26T13:09:49.363 に答える
5

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

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

(*x).Value初期化できるようにするには定数式でなければならないため、これは有効ではありませんValue。クラスValue内では、代わりにXas を使用すると、定数式として問題ありませんX::Value。しかし今回は、ポインターが含まれているためではありません (参照は定数式では同様に無効です)。

要約すると、これを行うことはできません。

Magic<T, someT>::type

::typeまた、T が int でない場合は T であると予想されます。IntWrapper<someT>それ以外の場合はT、列挙型、整数、ポインター、または参照型しか使用できないためです。後者の 2 つのケースでは、コンパイル時にポインタが指している、または参照によって参照されているものの「値」を取得できません。あなたがそれに満足しているなら、あなたの問題を解決するのは簡単です。

与えられたルールでは問題を解決できない状況に追い込まれたと思います。いくつかのステップを後退させ、解決しようとしている実際の問題を私たちに示してください。

于 2009-05-26T19:15:14.697 に答える
4

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

template<typename T>
void doSomething(const T& x)
{
    // ...
}
void doSomething(int x)
{
    // ...
}
于 2009-05-26T13:43:42.480 に答える
3

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

How about this then:


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 };
};
于 2009-05-26T13:15:56.217 に答える
3

他の投稿への追加enum {}: -hack を使用する必要はもうありません:

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;
}
于 2009-05-26T13:24:10.863 に答える
2

タイプとそのタイプのオブジェクトを指定すると、実際のオブジェクトにアクセスしながら、タイプが整数かどうかに基づいて決定できる C++ テンプレートが必要です。

型が整数であるかどうかに基づいて決定を下すことができます。問題は、任意の型のオブジェクトでテンプレートを宣言できないことです。したがって、型が整数かどうかを判断する方法に関する問題は議論の余地があります。

すべての回答で、元のテンプレートがきちんと変更されていることに注意してください

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

あなたの代わりに

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

しかし、C<int, 5>は完全に有効な宣言ですが、これは任意の型 T の場合には当てはまりません。適切なケースではC<float, 5.>、コンパイラ エラーが発生します。

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

レコードについては、2 番目のテンプレート引数が常に でありint、型が整数型の場合はその値を取得し、それ以外の場合は 0 を取得する場合は、次のように簡単に実行できます。

#include <limits>

template< typename T, int N >
class C {
    static const int Value = (std::numeric_limits<T>::is_integer) ? N : 0;
};
于 2009-05-26T14:23:50.977 に答える
2

次のように実行できます。

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;
}  
于 2009-05-26T13:20:38.127 に答える
0

テンプレートの特殊化は次のように行うことができます (コードは 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;
}

あなたの場合、char をクラス テンプレートの特殊化で必要なものに置き換える必要があります。さて、あなたが何を達成しようとしているのかはよくわかりませんが、上記の例が、テンプレートの特殊化を行う方法の良い指標になることを願っています.

于 2009-09-08T21:05:27.983 に答える
0

コードの簡単な修正 - 参照を緩めます:

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

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

テンプレート引数で参照を使用しても、実際には引数をどこにも渡していないため、とにかく無意味です。

于 2009-05-26T13:35:31.590 に答える
0

私が達成しようとしていたのは、コンパイル時に発生する次のようなものでした。

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

そもそも IntWrapper を使用していない理由がわかりません。int の場合、コンパイル時の整数定数を IntWrapper にラップする必要があるのはどこからですか?

そうしないと、実行時にのみ利用可能なデータを使用してテンプレートをインスタンス化しようとしているように見えます。

于 2009-09-08T21:29:46.237 に答える