“Ambiguous overload” в шаблонной перегрузке функции с variadic templates

219
14 мая 2018, 14:00

сообщество!

Помогите разобраться, почему следующий код не компилируется:

struct Format {};
template<typename F, typename ... Args>
void f(int, Args...) {}
template<typename F, typename T, typename ... Args>
void f(T, Args...) {}
int main () {
    f<Format>(1, 1);
}

Что интересно, если поменять сигнатуру на

template<typename F, typename T, typename ... Args>
void f(F, T, Args...)

или убрать первый шаблонный параметр, компилируется нормально.

Answer 1

Можно добавить явную проверку типа первого аргумента функции и отбрасывать один из шаблонов по SFINAE:

#include <iostream>
#include <type_traits>
struct Format {};
template<typename F, typename T, typename ... Args>
::std::enable_if_t<::std::is_same_v<T, int>>
f(T, Args...) {std::cout << "1" << ::std::endl;}
template<typename F, typename T, typename ... Args>
::std::enable_if_t<!::std::is_same_v<T, int>>
f(T, Args...) {std::cout << "2" << ::std::endl;}
int main () {
    f<Format>(1, 1);
    f<Format>("sdf", 1);
}

online compiler

В случае, если проверяемый параметр более сложный, например шаблон, то можно реализовать дополнительную проверку:

#include <iostream>
#include <type_traits>
struct Format {};
template<typename T> struct Meta{};
template<typename T> struct
is_meta_wrapper: public ::std::false_type {};
template<typename T> struct
is_meta_wrapper<Meta<T>>: public ::std::true_type {};
template<typename T>
constexpr auto const is_meta_wrapper_v{is_meta_wrapper<T>::value};
template<typename F, typename T, typename ... Args>
::std::enable_if_t<is_meta_wrapper_v<T>>
f(T, Args...) {std::cout << "1" << ::std::endl;}
template<typename F, typename T, typename ... Args>
::std::enable_if_t<!is_meta_wrapper_v<T>>
f(T, Args...) {std::cout << "2" << ::std::endl;}
int main () {
    f<Format>(Meta<int>{}, 1);
    f<Format>(1, 1);
    f<Format>("sdf", 1);
}

online compiler

READ ALSO
C++ WinAPI обработка исключений [требует правки]

C++ WinAPI обработка исключений [требует правки]

Напишите код для консольного приложения, обрабатывающего исключение при переполнении разрядной сетки

204
Решение ABA - проблемы

Решение ABA - проблемы

Необходимо решить ABA - проблему, используя младшие биты в качестве счетчика

237
Рекурсивный поиск файлов по маске во всех директориях и папках С++

Рекурсивный поиск файлов по маске во всех директориях и папках С++

Короче, проблема в том, что не получается попадать в другие диски и папки(выше чем лежит исполняемый файл)И вообще сильное ощущение, что написана...

242
задача про stack

задача про stack

Дана шеренга из n психовКаждому психу дан идентификатор от 1 до n На каждом ходе каждый псих, имеющий идентификатор больше, чем у психа справа...

197