2014-10-26 3 views
0

Я пишу две функции с тем же именем (и с аналогичными параметрами): Первый принимает переменное количество целочисленных параметров (минимум один). Второй принимает переменную величину struct coordinate в качестве параметров (опять же минимум один). struct coordinate может быть сконструирован как из int, так и для второго, можно взять int и std::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

Хорошо, основанный на моем новом понимании от комментария вы хотите что-то вроде этого:

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 
} 

Тогда вы просто урожденные d, чтобы написать черту типа, чтобы проверить, является ли все целым.

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, вы можете исправить это.

+0

Я ищу способ, чтобы три вызова на 'tmp' оставались неизменными и только изменяли реализацию. Чтобы гарантировать, что функция 'tmp' является частью API с этим вызовом 'signature'. – Jonas

+0

Что вы хотите, чтобы функция выполнялась? Сделайте одно, если все аргументы являются 'int' и другими, если они не все 'int'? – Barry

+0

В двух словах; да. Хотя количество параметров является переменным. – Jonas

Смежные вопросы