2016-09-29 9 views
1

数値データのベクトルを含むテンプレートクラスを作成しています(int、float、doubleなど)。そしてそれはデータ上でstd::abs()を呼び出す1つの操作を持っています。次のコードのようなもの。テンプレート引数またはtypenameを持つテンプレート関数

#include <iostream> 
#include <complex> 
#include <vector> 


template<typename T> class MyData 
{ 
public: 
    std::vector<T> data; 
    MyData<T> my_abs() const; 

}; 


template<typename T> 
MyData<T> MyData<T>::my_abs() const 
{ 
    MyData<T> output; 
    output.data.reserve(data.size()); 
    typename std::vector<T>::const_iterator it; 

    for (it = data.begin(); it != data.end(); it++) 
    { 
     output.data.push_back(std::abs(*it)); 
    } 
    return output; 
} 


int main() 
{ 
    MyData<double> A; 
    A.data = std::vector<double>(10, -1.0); 

    MyData<double> test = A.my_abs(); 

    for (auto el : test.data) 
    { 
     std::cout << el << std::endl; 
    } 
    return 0; 
} 

これは、int、float、doubleなどの型に対して正しく機能します。私はまた、このクラスをstd::complex<double>のような型で使用できるようにしたいと思います。

template<template<typename> class T, typename U> class MyData 
{ 
public: 
    std::vector<T<U>> data; 
    MyData<U> my_abs() const; 

}; 


template<template<typename> class T, typename U> 
MyData<U> MyData<T<U>>::my_abs() const 
{ 
    MyData<U> output; 
    output.data.reserve(data.size()); 
    typename std::vector<T<U>>::const_iterator it; 

    for (it = data.begin(); it != data.end(); it++) 
    { 
     output.data.push_back(std::abs(*it)); 
    } 
    return output; 
} 

私のテンプレートクラスには二つの引数、

error: wrong number of template arguments (1, should be 2) 
MyData<U> abs() const; 
    ^

は、理想的には私のようなものをしたいと思い期待して前のコードは動作しません:私は、テンプレートのテンプレート引数を使用することがわかっ周り探し

前のコード。 my_abs()関数は、テンプレートに渡されたテンプレート引数の型を返します。私はこれを達成することができます(または、それは同じテンプレートクラスを使用していても可能な場合)かわからない

int main() 
{ 
    MyData<std::complex<double>> A; 
    A.data = std::vector<std::complex<double>>(10, std::complex<double>(-1.0, -1.0)); 

    MyData<double> test = A.my_abs(); 

    for (auto el : test.data) 
    { 
     std::cout << el << std::endl; 
    } 
    return 0; 
} 

:私はstd::complex<double>を使用している場合例えば、次に私の主な機能は次のようなものを見ることができます。

+1

ただ、多分 'のstd ::複雑'のようなタイプのためのあなたの第一版を専門としています。 –

答えて

3

をキャストすることにより、適切なabsを選択することです。


例:

#include <iostream> 
#include <complex> 
#include <vector> 
#include <cmath> 
#include <utility> 

template<typename T> class MyData 
{ 
public: 
    std::vector<T> data; 
    using abs_type = decltype(std::abs(std::declval<T>())); 
    auto my_abs() -> MyData<abs_type> const; 
}; 

template<typename T> 
auto MyData<T>::my_abs() -> MyData<abs_type> const 
{ 
    MyData<abs_type> output; 
    output.data.reserve(data.size()); 
    typename std::vector<T>::const_iterator it; 

    for (it = data.begin(); it != data.end(); it++) 
    { 
     output.data.push_back(std::abs(*it)); 
    } 
    return output; 
} 

int main() 
{ 
    MyData<std::complex<double>> A; 
    A.data = std::vector<std::complex<double>>(10, std::complex<double>(-1.0, -1.0)); 

    auto test = A.my_abs(); 

    for (auto el : test.data) 
    { 
     std::cout << el << std::endl; 
    } 
    return 0; 
} 
+0

ありがとう、これは私が探していたものです。 – DSolis

0

あなたは、テンプレート機能が十分であり、このためにクラスを必要としない、このように

template<template<typename> class T, typename U> 
class MyData<T<U>> // <----- note the <T<U>> 
{ 
public: 
    std::vector<T<U>> data; 
    MyData<U> my_abs() const;  
}; 
+0

特化はなぜ必要ですか?彼の元のテンプレートは 'std :: complex 'のためにも機能します。 – user2296177

+0

@ user2296177 - OPが 'my_abs()'の戻り値の型を構築するために 'U '型(' double'部分)の形式 'T 'を抽出する必要があるので – max66

+0

@downvoter - できますか?私の答えで何が間違っているのか説明してください。 – max66

0

をあなたの専門分野を記述する必要があります。あなたのテンプレート関数にabs関数を与えることができます。

template<typename T, typename F> std::vector<T> my_abs(const std::vector<T> &in, F abs) { 
    std::vector<T> out; 
    for (auto &i: in) { 
     out.push_back(abs(i)); 
    } 

    return out; 
} 

std::vector<int> res = my_abs(in, special_abs); 

としてこれを呼び出すと、あなたが入力と出力のためのさまざまな種類を持っている場合、あなたはTUにパラメータ化することができます。


Jarod42は、すでに述べた@のように、これはstd::absようなオーバーロードされた機能は動作しません。 これを回避するには、ラムダを2番目の引数として指定します。

std::vector<int> res = my_abs(in, [](const auto& e) { return std::abs(e);}); 

別の回避策は、明示的にあなたの宣言でstd::abs(T)の戻り値の型を使用することができます適切な型に

std::vector<int> res = my_abs(in, static_cast<double(*)(double)>(std::abs)); 
+1

'std :: abs'に過負荷があるため、' my_abs(in、std :: abs); 'はコンパイルされません。 – Jarod42

+0

残念ながら、あなたは正しいです。 –

+0

あなたは 'my_abs(in、[const auto&e] {return std :: abs(e);});' – Jarod42

関連する問題