如何将具有不同第二类型的可变参数量的`std :: pair`传递给函数

时间:2016-07-14 09:51:28

标签: c++ templates c++11 variadic-templates std-pair

很抱歉由于问题的复杂性,无法解释标题中的主要问题 需要将各种类型的std::pair传递给下面的方法:

foo({1, 1} , {2, 2.2}, {3, "3"});  // 'first' is always `int`

但是,我无法找出如何使用可变参数模板定义foo()的语法?

这更像是化妆品的变化,其目的是避免锅炉板代码。因此排除了以下建议:

template<typename... Args>
void foo (Args&&... args) { ... }

template<typename T> using pair = std::pair<int, T>;
foo(pair<int>{1, 1} , pair<double>{2, 2.2}, pair<std::string>{3, "3"});

对于任何有兴趣的人,我要对各种pair做些什么。将在所有args...(使用数组技巧)上调用重载函数,并且所有second值将转换为std::string。对于那些不了解着名阵列技巧的人:

const string array[] = { MyFunc(std::forward<Pairs>(pairs)) ... };

类似(但不重复)的问题:Passing multiple std::pair to variadic template constructor using { }, { }

3 个答案:

答案 0 :(得分:2)

您只需使用此签名:

template<typename... Args>
void foo (std::pair<int, Args> ...args) { /*...*/}

template <typename ...Args> using pair = std::pair<int, Args...>;

编辑:如上所述,问题是关于构造std :: pair withot提供模板参数并将pair的第二部分转换为字符串。 重载()运算符可以写:

#include <iostream>
#include <vector>
#include <sstream>

struct Function{
    template <typename T>
    Function& operator()(int a, T b){
        ss << b;
        list.push_back(ss.str());
        ss.str("");
        return *this;
    }

    std::vector<std::string> get_string(){
        return list;
    }
    std::vector<std::string> list;
    std::stringstream ss;
};
int main(){
    Function foo;
    for(auto& s: foo(1, 3.0)(2,"foo")(3, 5.0f).get_string())
    {
        std::cout << s << std::endl;
    }
} 

答案 1 :(得分:1)

如果您打算以这种方式致电foo()

foo({1, 1} , {2, 2.2}, {3, "3"}); 

使用带有值而不是显式std::pair<int, int>{1,1}, std::pair<int, double>{1, 2.2}, ....的大括号......我认为这不可能。

如果你可以放弃大括号,那么以这种方式调用foo()

foo(1, 1 , 2, 2.2, 3, "3"); 

并在foo()内构建对,您可以执行类似

的操作
#include <string>
#include <utility>

void foo ()
 { 
   // do nothing ?
 }

template <typename T2, typename ... Ts>
void foo (int v1, const T2 & v2, const Ts & ... vs)
 { 
   std::pair<int, T2>  p { v1, v2 };

   // do something with p

   foo(vs...);
 }

int main()
 {
   foo(1, 1, 1, 2.2, 1, std::string("3"));

   return 0;
 }

但是,坦率地说,我不喜欢这个解决方案,因为不清楚这对是在调用foo(),所以我认为使用{{1}使用rahnema1的解决方案调用foo()是更好的方法}}

make_pair()

答案 2 :(得分:1)

我能得到的最近的是一对可变参数模板,其中第二个选项是模板类型,但每对都相同。

template<typename DataType, template<class, class> typename ...Pair>
    void foo(const std::pair<int, DataType>& nextParam, const Pair<int, DataType>& ...remainingParams);
void foo({1, "a"}, {2, "b"}, {3, "c"}); // works
void foo({1, "a"}, {2, 3.14}, {3, 'A'}); // doesn't work

也许有一种方法可以使模板参数可变。也就是说,我对此表示怀疑,从本质上讲,您需要能够指定包中的单个元素,或者使用包中的单个参数而不扩展它,但同时也要知道它实际上是一个包。