Рассмотрим этот код:
#include <vector>
#include <iostream>
enum class A
{
X, Y
};
struct Test
{
Test(const std::vector<double>&, const std::vector<int>& = {}, A = A::X)
{ std::cout << "vector overload" << std::endl; }
Test(const std::vector<double>&, int, A = A::X)
{ std::cout << "int overload" << std::endl; }
};
int main()
{
std::vector<double> v;
Test t1(v);
Test t2(v, {}, A::X);
}
Это печатает:
vector overload
int overload
Почему это не приводит к ошибке компиляции из-за неоднозначного разрешения перегрузки? Если второй конструктор удален, мы получим vector overload
два раза. Как / по какой метрике int
однозначно лучше, {}
чем для std::vector<int>
?
Сигнатура конструктора, безусловно, может быть обрезана дальше, но я просто обманулся эквивалентным фрагментом кода и хочу убедиться, что ничего важного не потеряно для этого вопроса.
c++
language-lawyer
overload-resolution
Макс Лангоф
источник
источник
{}
как блок кода, присваиваю 0 переменным - пример: const char x = {}; установлен в 0 (нулевой символ), то же самое для int и т. д.{}
эффективно делает в некоторых особых случаях, но это не всегда правильно (для начала,std::vector<int> x = {};
работает,std::vector <int> x = 0;
нет). Это не так просто, как «{}
назначить ноль».struct A { int x = 5; }; A a = {};
не присваивает ноль в любом смысле, он создаетA
сa.x = 5
. Это не похоже на тоA a = { 0 };
, что инициализируетсяa.x
до 0. Ноль не присущ{}
, он присущ тому, как каждый тип создается по умолчанию или инициализируется значением. Смотрите здесь , здесь и здесь .Ответы:
Это в [over.ics.list] , акцент мой
std::vector
Инициализируется конструктором и пулей в смелыми считает определенный пользователем converison. Между тем, дляint
, это преобразование идентичности, поэтому оно превосходит звание первого c'or.источник
0
имеет тип,int
но не типstd::vector<int>
, как это «как будто» по отношению к «нетипизированной» природе{}
?std::vector<int>
. Как вы сказали, я ожидал, что «тип параметра в конечном итоге решит, какой тип аргумента», и{}
«тип» (так сказать)std::vector<int>
не должен нуждаться в (не тождественном) преобразовании для инициализации astd::vector<int>
. Стандарт, очевидно, говорит, что это так, но это не имеет смысла для меня. (Имейте в виду, я не утверждаю, что вы или стандарт не правы, просто пытаюсь согласовать это с моими ментальными моделями.)