Используйте список инициализатора для создания одного элемента вектора - PullRequest
4 голосов
/ 16 апреля 2019

У меня есть функция func, которая перегружена и может принимать аргумент std::vector<Obj> или аргумент Obj.

#include <vector>
#include <iostream>

class Obj {
    int a = 6;
};

void func(const std::vector<Obj>& a) {
    std::cout << "here" << std::endl;
}

void func(const Obj& a) {
    std::cout << "there" << std::endl;
}

int main() {
    Obj obj, obj2;
    func({obj});
    func({obj, obj2});
}

Фактический результат:

there
here

Ожидаетсяoutput:

here
here

Кажется, {obj} инициализирует не вектор, а объект.Я предполагаю, что есть некоторый приоритетный порядок, когда дело доходит до того, какой тип он инициализирует.Как мне это точно контролировать?

(Примеры скомпилированы с помощью g ++ (Ubuntu 8.3.0-6ubuntu1) 8.3.0.)

Я нашел возможный дубликат ( c ++ 11инициализация вектора одного элемента в вызове функции ), хотя мой вопрос остается без ответа:

Я понимаю, что {obj} может разрешить объекту скорее вектор одного элемента, а первый имеет приоритет.Но есть ли способ использовать {} для создания вектора одного элемента (так что foo разрешает перегрузку std::vector)?Я мог бы создать вектор явно, но {} кажется лучше.

Ответы [ 2 ]

5 голосов
/ 16 апреля 2019

Как упомянуто в связанном вопросе-дубликате (оригинал), нет способа заставить разрешение в пользу перегрузки, принимая std::initializer_list.

Исходные подписи (для упрощения используйте int):

void func(const std::vector<int> &a); 
void func(const int &a);

Поскольку я сталкивался с этим много раз, я обычно делаю это:

func(std::vector<int>{10});

Я не знаю ни одного более короткого способа сделать это, потому что использование фактического типа std::initializer_list, который бысделать то же самое еще более многословно.Но, с другой стороны, это, по крайней мере, делает то, что вы делаете, совершенно ясно, поскольку {10} действительно неоднозначно, если не сопровождается типом.

3 голосов
/ 16 апреля 2019

Вы не можете.

Выдержка (из здесь , выделение мое):

"[...], если список инициализатора имеет один элемент типа E, и либо T не является ссылочным типом, либо его ссылочный тип связан со ссылкой на E, объект или ссылка инициализируются из этого элемента (путем копирования-инициализации для копирования-списка-инициализацииили прямая инициализация для прямой инициализации списка) "

Поэтому в вашем связанном примере {obj} будет" затухать "до obj и перегрузкаразрешится в void func(const Obj& a).

Как указано в другом ответе, вы можете явно позвонить func(std::vector {obj}), чтобы вместо этого вызвать векторную перегрузку.

...