2

テンプレート クラスを作成し、テンプレート パラメーターの typeid に応じて異なるアクションを実行する場合、これをどのようにコーディングすればよいでしょうか?

たとえば、次のテンプレート クラスがあり、int か string かに応じてメンバー フィールド データを初期化します。

#include <string>

template <class T>
class A
{
private:
    T data;
public:
    A();
};

// Implementation of constructor
template <class T>
A<T>::A()
{
    if (typeid(T) == typeid(int))
    {
        data = 1;
    }
    else if (typeid(T) == typeid(std::string))
    {
        data = "one";
    }
    else
    {
        throw runtime_error("Choose type int or string");
    }
}

ただし、このコードは、次のメイン ファイルではコンパイルされません。

#include "stdafx.h"
#include "A.h"
#include <string>

int _tmain(int argc, _TCHAR* argv[])
{
    A<int> one;
    return 0;
}

エラーは次のとおりです: エラー C2440: '=' : 'const char [2]' から 'int' に変換できません。コードのその部分に到達します。

次に、この例 (テンプレート変数の型に基づいて異なるメソッドを実行する) に従って、次の Ah ファイルを試しましたが、A(void) が A.obj で既に定義されていることを示すいくつかのリンカー エラーが発生しました。

#include <string>

template <class T>
class A
{
private:
    T data;
public:
    A();
    ~A();
};

// Implementation of constructor
template <>
A<int>::A()
{
    data = 1;
}
template <>
A<std::string>::A()
{
    data = "one";
}

このコードを起動して実行する方法を知っている人はいますか? また、テンプレート クラスでそのような if-else ステートメントを使用すると、テンプレートの機能が失われる可能性があることも認識しています。これをコーディングするより良い方法はありますか?

編集: Torsten (下記) との話し合いの後、次の Ah ファイルができました。

#pragma once

#include <string>

// Class definition
template <class T>
class A
{
public:
    A();
    ~A();
private:
    T data;
};

// Implementation of initialization
template < class T > 
struct initial_data
{
  static T data() { throw runtime_error("Choose type int or string"); }
};

template <> 
struct initial_data< int >
{
    static int data() { return 1; }
};

template <> 
struct initial_data< std::string >
{
    static std::string data() { return "one"; }
};

// Definition of constructor
template <class T>
A<T>::A()
  : data( initial_data< T >::data() ) 
{
}

そして次のメイン:

#include "stdafx.h"
#include "A.h"
#include <string>

int _tmain(int argc, _TCHAR* argv[])
{
    A<int> ione;

    return 0;
}

私が今得るリンカーエラーは次のとおりです: Test template 4.obj : error LNK2019: unresolved external symbol "public: __thiscall A::~A(void)" (??1?$A@H@@QAE@XZ) referenced in関数 _wmain

4

3 に答える 3

3

2番目のソリューションは正しいです。必要なのは、テンプレートの特殊化(宣言と実装を一緒に保つ)です。

#include <string>

template <class T>
class A
{
private:
    T data;
public:
    A();
    ~A();
};

template <>
class A <std::string>
{
private:
  std::string data;
public:
  A() { data = "one"; }
};

template <>
class A <int>
{
private:
  int data;
public:
  A() { data = 1; }
};

より洗練されたソリューションを提案する場合は、コンストラクターにパラメーターを追加し、テンプレートの特殊化を回避します。

template <class T>
class A
{
private:
    T data;
public:
    A( T value ) : data( value ) {}
    virtual ~A() {}
};
于 2012-07-04T09:13:13.930 に答える
3

明示的な専門化が進むべき道です。

Ahをいくつかの.cppに含めていると思いますが、それが問題の根本的な原因です。

特殊化は定義であり、A :: A()とA :: A()の定義は1つだけである必要があるため、それらは1つの.cppにのみ含まれている必要があります。

明示的な特殊化を.cppに移動する必要があります

template <>
A<int>::A()
{
    data = 1;
}
template <>
A<std::string>::A()
{
    data = "one";
}

ああで彼らのために宣言をしてください

template<> A<int>::A();
template<> A<std::string>::A();

コンパイラーは、それらが明示的に特殊化されていることを認識し、自動のものを追加しようとしないようにします。

編集:これらの4つのファイルでは、g ++ m.cppf.cppa.cppはエラーを表示しません。

// a.h
#define A_H

#include <string>

template <class T>
class A
{
private:
    T data;
public:
    A();
};

template<> A<int>::A();
template<> A<std::string>::A();

#endif

// a.cpp
#include "a.h"

template <>
A<int>::A()
{
    data = 1;
}
template <>
A<std::string>::A()
{
    data = "one";
}

// f.cpp
#include "a.h"

int f()
{
    A<int> one;
    A<std::string> two;
}

// m.cpp
#include "a.h"

int f();

int main()
{
    A<int> one;
    A<std::string> two;
    f();
}
于 2012-07-04T09:10:14.567 に答える
2

Tに依存する動作をしたいのがc'torだけの場合は、これを別の構造体に分解することをお勧めします。

template < class T > 
struct initial_data
{
  static T data() { throw runtime_error("Choose type int or string"); }
};

template <> 
struct initial_data< int >
{
    static int data() { return 1; }
}

template <> 
struct initial_data< std::string >
{
    static std::string data() { return "1"; }
}

テンプレートパラメータでクラスを特殊化する場合、特殊化が異なればタイプもまったく異なり、データと関数のセットも異なる可能性があります。

ついに:

template <class T>
A<T>::A()
  : data( initial_data< T >::data() ) 
{
}

Torstenよろしくお願いします

于 2012-07-04T09:11:41.013 に答える