24
#include <boost/type_index.hpp>
#include <iostream>
#include <vector>

int main()
{
    std::vector v{2, 3.14};
    std::cout << boost::typeindex::type_id_with_cvr<decltype(v)>().pretty_name() << '\n';

    std::cout << "size: " << v.size() << '\n';
    for (auto x : v)
        std::cout << "- " << x << '\n';
}

The output is:

std::vector<double, std::allocator<double> >
size: 2
- 2
- 3.14

std::vector instantiation uses auto-type-deduction (CTAD).

Apparently, the initializer_list constructor is used (checked), but why does it accept both an int and a double and still deduces the type as vector<double> ?
If I increase the number of elements (while mixing int and double), compilation fails.

The same result with gcc and clang

$ g++ --version
g++ (GCC) 13.0.1 20230401 (Red Hat 13.0.1-0)

$ clang++ --version
clang version 16.0.1 (Fedora 16.0.1-1.fc38)
genpfault
  • 51,148
  • 11
  • 85
  • 139
Tootsie
  • 655
  • 3
  • 11

1 Answers1

23

There are two instances of overload resolution happening here. The first is to deduce the template argument. Since the two types in the init-list are different, the size+value constructor (or more formally, the deduction guide generated from said constructor) is picked here, deducing the type to be double.

Then overload resolution runs again to create the object. With the type now known as double, the list constructor is now valid, and thus used to initialize the object.

chris
  • 60,560
  • 13
  • 143
  • 205
  • 1
    So if you wanted to get a vector of size 2, filled with values all equal to 3.14, would you be forced to explicitly indicate the template argument as `std::vector`? – Fabio says Reinstate Monica Apr 26 '23 at 14:30
  • 7
    @FabiosaysReinstateMonica, I believe using parentheses instead of braces would do that because the list constructor is removed from the picture entirely. – chris Apr 26 '23 at 14:32
  • 4
    So you are saying that two different constructors are used for template type deduction and initialization. Shouldn't the same constructor be used for both actions? I can't get my head over this. – Karen Baghdasaryan Apr 26 '23 at 16:29
  • @KarenBaghdasaryan, It is a little weird. I can't say why it doesn't require that. – chris Apr 26 '23 at 16:43
  • Can you provide any section in standard with will address this issue, or at least some non-official resources? I would be very thankful. – Karen Baghdasaryan Apr 26 '23 at 20:00
  • 2
    @KarenBaghdasaryan, I was deliberately avoiding the standard itself on this one because there's no telling how long I'd be trapped in there, but I can offer [this CppCon video](https://youtu.be/-H-ut6j1BYU?t=1955) (at the relevant slide). I wonder if the proposal has motivation for allowing different results when a constructor or its generated guide is chosen in both cases or if the idea was to layer CTAD on top and that fell out as just a consequence. – chris Apr 26 '23 at 20:10