Для меня, используя более зернистую версию примера преторианской работал для меня. Я определил что-то вроде is_compat<T, Arg>
, а затем подайте это в выражение std::enable_if<>
(используя std::decay<>
, чтобы упростить сопоставление).
EDIT: Найдено std::is_convertible
, MUCH simpler.
Автономные Пример:
Инлайн Пример:
#include <type_traits>
// Syntactic sugar
using std::enable_if;
using std::is_convertible;
template<bool Expr, typename Result = void>
using enable_if_t = typename enable_if<Expr, Result>::type;
template<typename From, typename To>
using enable_if_convertible_t = enable_if_t<is_convertible<From, To>::value>;
Затем вы можете сделать Перегрузки как:
template<typename ... Args>
void my_func(Args&& ... args) {
cout << "1. my_func<Args...>(" << name_trait_list<Args&&...>::join() << ")" << endl;
}
// Use template with enable_if to catch as many types as possible
template<typename T1,
typename = enable_if_convertible_t<T1, string>>
void my_func(int y, T1&& z) {
cout
<< "2. my_func<T1:string>(int, " << name_trait<decltype(z)>::name()
<< ")" << endl;
}
// Example using multiple types (let compiler handle the combinatorics)
template<typename T1, typename T2,
typename = enable_if_t<is_convertible<T1, string>::value &&
is_convertible<T2, double>::value>>
void my_func(int y, T1&& z, T2&& zz) {
cout
<< "3. my_func<T1:string, T2:double>(int, "
<< name_trait<decltype(z)>::name() << ", "
<< name_trait<decltype(zz)>::name() << ")" << endl;
}
(Примечание: name_trait*
является домашней выпечки класса)
Пример вывода:
>>> (my_func(1, 2, 5, string("!!!")));
1. my_func<Args...>(int&&, int&&, int&&, std::string&&)
>>> (my_func(3, string("Hello")));
2. my_func<T1:string>(int, std::string&&)
>>> (my_func(4, (const string&)string("kinda")));
2. my_func<T1:string>(int, const std::string&)
>>> (my_func(5, "World"));
2. my_func<T1:string>(int, const char[6]&)
>>> (my_func(6, var));
2. my_func<T1:string>(int, char[6]&)
>>> (my_func(7, var, 12));
3. my_func<T1:string, T2:double>(int, char[6]&, int&&)
>>> (my_func(9, var, 12.0));
3. my_func<T1:string, T2:double>(int, char[6]&, double&&)
Не должно быть 'is_related, Args >> ...'? Кроме того, почему это должно быть отключено, если типы одинаковы? –
0x499602D2
@ 0x499602D2 Нет, 'Args' необходимо развернуть в' is_related', потому что вы хотите, чтобы основной шаблон 'is_related' был выбран, когда' sizeof ... (Args)! = 1'. Вы хотите отключить его, когда типы совпадают, потому что в этом случае вы хотите, чтобы конструктор copy/move был выбран вместо совершенной пересылки. – Praetorian
О, я не заметил, что в основном шаблоне был пакет шаблонов.Во всяком случае, вы говорите, что если вы делаете 'wrapper w (x, y, z)' где '{x, y, z}' все типа 'Obj' (что означает' int'), то шаблон конструктора * должен 't * быть выбрано? Я предполагаю, что вы думаете, что они не должны, потому что вы используете 'DisableIf'. Но я думаю, что это должно быть 'EnableIf'. –
0x499602D2