0

This example fails to compile unless I uncomment the default constructor declaration:

#include<unordered_map>
#include <iostream>

struct foo{
    int data;
    /*foo(){
        data = 0;
        std::cout << "DEFAULT\n";
    }*/
    foo(int d){
        data = d;
        std::cout << "PARAM\n";
    }
};

struct bar{
    std::unordered_map<int, foo> map;
    foo getElem(int i){
        return map[i];
    }
};

int main() {
    bar b;
    foo f1(1);
    foo f2(2);
    b.map.insert({1,f1});
    b.map.insert({2,f2});

    foo f3 = b.getElem(1);
}
/opt/compiler-explorer/gcc-10.2.0/include/c++/10.2.0/tuple:1689:70: error: no matching function for call to 'foo::foo()'
 1689 |         second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...)
      |                                                                      ^

When I uncomment the default constructor declaration and successfully compile, the breadcrumbs show that the default constructor is not ever called.

What is going on here? A similar problem is due to a most vexing parse, but without any explicit constructor calls I am not sure if that is the case here.

This answer provides hints as to why an unordered_map would implicitly call a default constructor. Is the issue some combination of the documented behavior described and MVP?

link to godbolt

Cam
  • 23
  • 2
  • 2
    `the breadcrumbs show that the default constructor is not ever called.` it _could_ be, if `return map[i];` accesses an element which does not exist. – tkausl Mar 29 '21 at 22:10

1 Answers1

1

When the compiler compiles this line:

foo f3 = b.getElem(1);

1 is passed as a parameter to a function (unless a whole lot of optimization magic occured, which is not guaranteed). This function cannot know that 1 will never be a missing key. As such, the code that allocates an entry in the map is called. And what is passed to this code, if the key is missing ? Yep, a default-constructed foo.

So, in a nutshell, you know that

the default constructor is not ever called

but the compiler and linker don't.

Jeffrey
  • 11,063
  • 1
  • 21
  • 42