У меня проблема с постоянным одиночным элементом std :: vector при прохождении через функцию. Компилятор C++ автоматически вызывает неправильную функцию, если переменная std :: vector содержит единственный элемент. Такова политика дизайна C++. Однако есть ли какой-либо явный способ указать в таком случае. Вот примеры проблем
assume i have two overload functions both have the same name "foo"
void foo(const std::vector<int> A)
{
// do vector operator
printf("vector thing");
}
void foo(int a)
{
// do integer operator
printf("integer thing")
}
В общем случае обе эти функции вызываются правильно
foo({1,2,3}); // print do vector thing
foo( 3 ); // print do integer thing
однако из правила С ++. при звонке
foo({5}); // print do integer thing ( I want it to call as vector )
один из методов - создать переменную
std::vector<int> B = { 5 };
чтобы решить эту проблему.
Мне кажется, этот метод немного неуклюжий. Есть ли какой-либо метод, который может аннулировать компилятор для обработки {5} как 5 и вызова foo (int a).
Примечание: вот ссылка, объясняющая, в чем проблема С ++ 11 инициализация одноэлементного вектора при вызове функции
foo(std::vector<int>({5}));




Нет, потому что начиная с C++ 17 все еще действуют правила, описанные в связанном ответе.
Однако вы можете создать временную вместо переменной.
foo(std::vector{5}); // C++17 with class type deduction
foo(std::vector<int>{5}); // older versions
Вам нужна еще одна перегрузка, взяв в качестве параметра std::initializer_list:
void foo(std::initializer_list<int> A)
{
foo(std::vector<int>(A.begin(), A.end()));
}
Если вы всегда вызываете эту функцию, создавая векторы непосредственно с помощью {...}, а не используя переменные std::vector, то вы можете полностью удалить перегрузку std::vector и работать непосредственно с std::initializer_list.
Один из способов устранить неоднозначность вызова функции - сделать целочисленную перегрузку шаблоном функции:
template <class Int> void foo(Int a)
{
std::printf("generalized (maybe integer) thing\n");
}
Таким образом, призыв
foo({3});
будет считать, что функция без шаблона лучше подходит, в то время как foo(3) создает и вызывает шаблон функции. Это потому, что {3} - это std::initializer_list<int> с одним элементом в контексте вывода типа. Вы также можете перенаправить на исходную функцию foo(int a) следующим образом:
void fooImpl(int a)
{
std::printf("integer thing\n");
}
template <class Int> void foo(Int&& a)
{
fooImpl(std::forward<Int>(a));
}
Это отказывается компилироваться, когда, например, вызов foo с аргументом, который нельзя преобразовать в целое число, что может быть желательным ограничением использования. Кроме того, очень маловероятно, что вы столкнетесь с накладными расходами на производительность из-за промежуточной функции пересылки.
Учитывая, что это большой источник путаницы, просто напишите
std::vectorявно, и у вас не будет проблем.