Минимальный пример программы:
#include <vector>
void f(std::vector<int>) {} // #1
void f(std::vector<void *>) {} // #2
int main() { f({ 1 }); }
Было бы интуитивно понятно, что это допустимая программа: вызов с использованием перегрузки # 1 будет действительным, вызов с использованием перегрузки № 2 будет некорректнымпоэтому перегрузка № 1 должна быть выбрана.Это то, что делает clang.
К сожалению, по стандарту кажется, что это неоднозначно, потому что есть конструктор для std::vector<void *>
, который можно вызвать с помощью int
, неявно преобразовав его в size_t
.Тот факт, что этот конструктор равен explicit
, должен игнорироваться при разрешении перегрузки, если бы эта перегрузка была выбрана, программа просто не работала бы.GCC отклоняет вызов как неоднозначный, и похоже, что это правильно.
Я могу изменить код, чтобы позволить GCC принять вызов, указав имя типа: f(std::vector<int>{ 1 });
.В качестве альтернативы я могу использовать диспетчеризацию тегов с параметрами по умолчанию, чтобы позволить явно указать, какую перегрузку использовать, и в то же время разрешить принимать существующие вызовы, как и раньше.
Оба из них приемлемы, но довольно быстро становятся достаточно многословными при возвращении креальный кодЕсть ли другой вариант, который позволяет мне не указывать полное имя типа, но придерживаться текущих перегрузок?На мгновение я подумал, что { 1, }
может сработать, но, конечно, это не так, int i = { 1, };
также вполне допустимо, что нельзя использовать, чтобы избежать # 2.
Если это помогает исключитьВ некоторых альтернативах реальный код включает в себя std::vector<int>
и std::vector<T>
и включает вызов со списком инициализированных скобками, содержащим одно целое выражение, но T
- это пользовательский тип, а не встроенный тип, ивыражение не является постоянным значением.
«Нет» является приемлемым ответом, но в этом случае, пожалуйста, уточните, пожалуйста, покажите, что такой опции нет.