2017-08-09 35 views
1

多くのタイプで動作するクラスを作成したいと思います。 しかし、このクラスの要素をタイプではなく、文字列でインスタンス化したい(intの代わりに"int"を使用するなど)。このクラスを使用する際には、広範なディスパッチャ関数を作成する必要はありません。タイプの代わりに文字列を使用したテンプレート

最初の1:

template <typename T> 
class Tab { 
public : 

    Tab(std::size_t length) { 
    T* tab_[length]; 
    tab = tab_; 
    } 

    T* tab; 

    T operator[](std::size_t i) { 
    return tab[i]; 
    } 
}; 

Tab getTab(std::string type, std::size_t length) { 

    if (type == "int") { 
     Tab<int> tab(length); 
    } else if (type == "double") { 
     Tab<double> tab(length); 
    } 

    return tab; 
} 

秒1:両方の試みはコンパイルされません

typedef boost::variant<int, double> numeric; 
typedef boost::variant<int*, double*> numeric_ptr; 

class Tab { 
public : 

    Tab(std::string type, std::size_t length) { 
    if (type == "int") { 
     tab = new int[length]; 
    } else if (type == "double") { 
     tab = new double[length]; 
    } 
    } 

    numeric_ptr tab; 

    numeric operator[](std::size_t i) { 
    return tab[i]; 
    } 
}; 

は小さなクラス Tabで、私は2つの "ソリューション" を試してみました。私は私の問題にそれほど複雑ではない解決策を持っているのが大好きです。

編集:なぜ、最初にタイプ名の代わりに文字列を使用していますか?

テンプレート化されたクラスを使用する多くの関数があります。各ファンクションでは、テンプレート化されたクラスのtypenameを文字列として認識できるので、このようなディスパッチ関数を使用する必要があります。https://github.com/privefl/bigstatsr/blob/master/src/colstats.cpp。このような20の関数がある場合、それらのすべての関数に対してディスパッチ関数を書くのは面倒です(エラーが発生しやすい)。

私は、クラスのインスタンス化のためのディスパッチ関数を1つだけ作成し、このテンプレート化されたクラスのインスタンスを必要とするすべての関数でこの関数を使用したいと思います。

+1

「getTab」を関数テンプレートにしてみませんか? – 0x499602D2

+0

@ scohe001編集:コンパイルしないでください。 –

+0

@ 0x499602D2それは私が避けたいものです。私はテンプレートにするが、文字列でしたい。 –

答えて

5

あなたのような何かを行うことがあります。

template <typename T> 
class Tab { 
public: 
    Tab(std::size_t length) : tab(length) {} 

    // ... 
private: 
    std::vector<T> tab; 
}; 

boost::variant<Tab<int>, Tab<double> > 
CreateTab(const std::string& type, std::size_t length) 
{ 
    if (type == "int") { 
     return Tab<int>(length); 
    } else if (type == "double") { 
     return Tab<double>(length); 
    } 
    throw std::runtime_error("Bad type"); 
} 
+0

有望ですね。私は明日あなたの解決策を試し、あなたに戻ってきます。 –

+0

** 'boost :: variant 、Tab >'を 'Tab'クラスの要素として使うことはできません。** boost :: variant 、Tab > 'Tab'クラスのメンバとメソッドを持っています。 –

2

私は「文字列のテンプレート」ではないだろうと戻り値の型に変異型ではなく、テンプレートを返します。

getTab<int>(17); 

この場合でも、あなたはあなたの質問で参照していた "高価なディスパッチャ機能"は必要ありません。あなただけのTabのラップタイプのテンプレートとしてそう

template < typename T > 
void algorithm(Tab<T> const& t) { ... } 

私も使用してメモリの正確を容易にするためにstd::vectorで裸のポインタを置き換えます。

#include <vector> 

template <typename T> 
class Tab { 
    std::vector<T> tab; 
public : 

    Tab(std::size_t length) : tab(length) {} 

    T operator[](std::size_t i) { 
    return tab[i]; 
    } 
}; 

template < typename T > 
Tab<T> getTab(std::size_t length) 
{ 
    return Tab<T>(length); 
} 

int main() 
{ 
    auto ti = getTab<int>(17); 
    auto td = getTab<double>(29); 
} 
+0

これが文字列を型名にディスパッチしないようにする方法がわかりません。 –

+0

@F.Privéなぜ最初にタイプ名の代わりに文字列を使用していますか?この例では、明らかに必要はありません。 –

+0

公正な質問。私の編集を参照してください。 –

関連する問題