简体   繁体   English

具有原始类型的模板向量类型

[英]template vector type with primitive type

I want to template a function with both primitive type ( int , float , double ) and vector type ( vector<int> , vector<float> , vector<double> ).我想用原始类型( intfloatdouble )和向量类型( vector<int>vector<float>vector<double> )模板化 function 。 Below is my code.下面是我的代码。 I would like to know if there is a way to template parseKeyValue() with less code duplication when building different vector cases.我想知道在构建不同的向量案例时是否有一种方法可以使用更少的代码重复来模板化parseKeyValue() Thanks!谢谢!

#include <iostream>
#include <typeinfo>
#include <vector>
#include <string>
#include <sstream>
#include <iterator>


using namespace std;


template<class T> T parseKeyValue(stringstream& ss){
    T value;
    while(ss >> value){};
    return value;
}

template<> vector<string> parseKeyValue(stringstream& ss){
    vector<string> value;
    string item;
    while(ss >> item) value.push_back(item);
    return value;
}

template<> vector<int> parseKeyValue(stringstream& ss){
    vector<int> value;
    int item;
    while(ss >> item) value.push_back(item);
    return value;
}


template<typename T>
ostream& operator<<(ostream& os, const vector<T>& v){
    std::copy(v.begin(), v.end(), std::ostream_iterator<T>(os, " "));
    return os;
}


int main(){

    stringstream ss("1-2-3 7-8-9");
    vector<string> t = parseKeyValue< vector<string> >(ss);
    cout << t << endl;

    stringstream ss2("123 789");
    vector<int> t2 = parseKeyValue< vector<int> >(ss2);
    cout << t2 << endl;

    stringstream ss3("123 789");
    int t3 = parseKeyValue< int >(ss3);
    cout << t3 << endl;

    return 0;
}

You can wrap it in a class template, which could be partial specialized.您可以将其包装在 class 模板中,该模板可能是部分专用的。

template<class T> 
struct Wrapper {
    static T parseKeyValue(stringstream& ss){
        T value;
        while(ss >> value){};
        return value;
    }
};

template<class T> 
struct Wrapper<std::vector<T>> {
    static vector<T> parseKeyValue(stringstream& ss){
        vector<T> value;
        T item;
        while(ss >> item) value.push_back(item);
        return value;
    }
};

template<class T> T parseKeyValue(stringstream& ss){
    return Wrapper<T>::parseKeyValue(ss);
}

LIVE居住

Or apply SFINAE with template overloading.或者将SFINAE与模板重载一起应用。

template <typename T>
struct is_vector : std::false_type {};
template <typename T>
struct is_vector<std::vector<T>> : std::true_type {};

template<class T> 
std::enable_if_t<!is_vector<T>::value, T>
parseKeyValue(stringstream& ss) {
    T value;
    while(ss >> value){};
    return value;
}

template<class T> 
std::enable_if_t<is_vector<T>::value, T>
parseKeyValue(stringstream& ss) {
    T value;
    typename T::value_type item;
    while(ss >> item) value.push_back(item);
    return value;
}

LIVE居住

The way you have defined your functions you would need partial specialisations for your functions – which is not legal in C++.您定义函数的方式需要对函数进行部分特化——这在 C++ 中是不合法的。 Even if it was legal you have no parameters for deducing the template type, so you always would have to specify the template arguments explicitly:即使它合法的,您也没有用于推断模板类型的参数,因此您始终必须明确指定模板 arguments:

std::vector<int> v = parseKeyValue<std::vector<int>>(...);
//                                ^        ^       ^

as deduction from assignment to variable is not possible.因为不可能从赋值中扣除变量。

If you change the function signature to filling a function parameter, you can operate with overloads:如果将 function 签名更改为填充 function 参数,则可以使用重载操作:

template <typename T>
void parseKeyValue(T& t, std::istream& s);

template <typename T>
void parseKeyValue(std::vector<T>&, std::istream& s);

And you can even have a variant for generic containers:你甚至可以有一个通用容器的变体:

template <typename T, template <typename> class Container >
void parseKeyValue(Container<T>, std::istream& s);

Note that I changed parameter from std::stringstream to std::istream , which is less restrictive, so you could use the functions with eg std::cin , too.请注意,我将参数从std::stringstream更改为std::istream ,这限制较少,因此您也可以将这些函数与例如std::cin一起使用。

This way, you do not rely on partial specialisations and additionaly can profit from template argument deduction:这样,您就不必依赖部分特化,并且可以从模板参数推导中获益:

int n;
parseKeyValue(n, std::cin); // selects non-container overload
std::vector<int> v;
parseKeyValue(v, std::cin); // selects vector overload, as more specialised
std::list<int> l;
parseKeyValue(l, std::cin); // selects generic container overload

Side note:边注:

while(ss >> value){};

in your original non-vector version would read any values available and discard all but very last.在您的原始非向量版本中,将读取任何可用的值并丢弃所有值,但最后。 Is this intended?这是故意的吗?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM