重载时区分函数

时间:2014-10-26 19:19:13

标签: c++ c++11 variadic-templates overloading

我正在编写两个具有相同名称的函数(并且具有相似的参数): 第一个只采用可变数量的整数参数(最小一个)。 第二个采用可变量struct coordinate作为参数(再次最小值为1)。 struct coordinate可以从intstd::vector<int>构建,因此第二个也可以采用intstd::vector<int>。 问题是如果第二个函数的第一个参数是int,则编译失败。 是否可以使main()中的第三行调用另一个tmp函数? 我目前的实施情况如下:

int main(int argc, char** argv)
{
    tmp(1, 2, 3, 4, 5);                   // OK! First function calls 'single'
    tmp(std::vector<int>{1, 2, 3}, 4, 5); // OK! Second function calls 'multi'
    tmp(1, std::vector<int>{2, 3}, 4);    // Compilation error! First function calls 'single'

    return 0;
}

编译器输出:

prog.cpp: In instantiation of ‘std::vector<int> tmp(int, types ...) [with types = {std::vector<int, std::allocator<int> >, int}]’:
prog.cpp:58:34:   required from here
prog.cpp:29:23: error: no matching function for call to ‘single(std::vector<int>&, std::vector<int>&, int&)’
  single(list, ints ...);
                       ^
prog.cpp:29:23: note: candidates are:
prog.cpp:12:6: note: void single(std::vector<int>&, int)
 void single(std::vector<int>& list, int first)
      ^
prog.cpp:12:6: note:   candidate expects 2 arguments, 3 provided
prog.cpp:18:6: note: template<class ... types> void single(std::vector<int>&, int, types ...)
 void single(std::vector<int>& list, int first, types ... ints)
      ^
prog.cpp:18:6: note:   template argument deduction/substitution failed:
prog.cpp:29:23: note:   cannot convert ‘ints#0’ (type ‘std::vector<int>’) to type ‘int’
  single(list, ints ...);
                       ^

我目前的实施:

#include <iostream>
#include <vector>

struct coordinate
{
    std::vector<int> c;

    coordinate(std::vector<int> A) : c(A) {}
    coordinate(int A) : c{A} {}
};

// Function to end the recursive call to single
void single(std::vector<int>& list, int first)
{
    list.push_back(first);
}

// Recursive function to store the parameters (only int)
template <typename... types>
void single(std::vector<int>& list, int first, types ... ints)
{
    list.push_back(first);
    single(list, ints ...);
}

// 'First' function
template <typename... types>
std::vector<int> tmp(int i, types ... ints)
{
    std::vector<int> list;
    list.push_back(i);
    single(list, ints ...);
    return list;
}

// Function to end the recursive call to multi
void multi(std::vector<std::vector<int> >& list, coordinate first)
{
    list.push_back(first.c);
}

// Recursive function for storing the parameters (only 'coordinate')
template <typename... types>
void multi(std::vector<std::vector<int> >& list, coordinate first, types ... coords)
{
    list.push_back(first.c);
    multi(list, coords ...);
}

// 'Second' function
template <typename... types>
std::vector<std::vector<int> > tmp(coordinate i, types ... coords)
{
    std::vector<std::vector<int> > list;
    list.push_back(i.c);
    multi(list, coords ...);
    return list;
}

1 个答案:

答案 0 :(得分:1)

好的,基于我对评论的新理解,你想要这样的东西:

template <typename... Args>
typename std::enable_if<all_ints<Args...>::value>::type
tmp(Args... args) {
   // the all integer version
}

template <typename... Args>
typename std::enable_if<!all_ints<Args...>::value>::type
tmp(Args... args) {
   // the coordinate version
}

然后你只需要编写类型特征来检查是否所有内容都是整数。

template <typename... T>
struct all_ints : std::true_type { };

template <typename T, typename... Rest>
struct all_ints<T, Rest...>
: std::integral_constant<bool, 
      std::is_integral<T>::value && all_ints<Rest...>::value>
{ }

我使用std::is_integal来处理所有整数类型。如果你真的想要明确int,你可以解决它。