C++14 errors in C++17, LNK2019, C1001 altogether

There’s a pretty straightforward 3-file source.

Compiling with cl.exe.

  • Using /std:c++17 it compiles with c++14 errors (error C3533: a parameter cannot have a type that contains ‘auto’).
  • Using /std:c++20 it compiles but gives an LNK2019.
  • When using /std:c++20, BUT WITH #include <string> moved from serialization.cpp => database.h, it gives a fatal internal compiler error C1001.

The source files:

database.h:

#pragma once

#include <map>

struct map_manip 
{
    void operator()(auto& map, uint8_t size = 2);
};

database.cpp:

#include "database.h"

void map_manip::operator()(auto& map, uint8_t size)
{
}

serialization.cpp:

#include "database.h"

#include <string>

struct entry
{
    std::map<std::string_view, uint32_t> units;
};

int main()
{
    entry x;
    map_manip y;
    y(x.units);
}

Compiling with c++17:

D:devLocalTest>cl /EHsc /std:c++17 serialization.cpp database.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

serialization.cpp
D:devLocalTestdatabase.h(8): error C3533: a parameter cannot have a type that contains 'auto'
serialization.cpp(12): error C2664: 'void map_manip::operator ()(unknown-type,uint8_t)': cannot convert argument 1 from 'std::map<std::string_view,uint32_t,std::less<std::string_view>,std::allocator<std::pair<const std::string_view,uint32_t>>>' to 'unknown-type'
D:devLocalTestdatabase.h(8): note: see declaration of 'map_manip::operator ()'
database.cpp
D:devLocalTestdatabase.h(8): error C3533: a parameter cannot have a type that contains 'auto'
database.cpp(3): error C3533: a parameter cannot have a type that contains 'auto'
Generating Code...

These errors would’ve been valid in c++14, I believe, but shouldn’t be the case here as we compile with c++17. Correct me if I get it wrong, please.


Compiling with c++20:

D:devLocalTest>cl /EHsc /std:c++20 serialization.cpp database.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

serialization.cpp
database.cpp
Generating Code...
Microsoft (R) Incremental Linker Version 14.29.30133.0
Copyright (C) Microsoft Corporation.  All rights reserved.

/out:serialization.exe
serialization.obj
database.obj
serialization.obj : error LNK2019: unresolved external symbol "public: void __thiscall map_manip::operator()<class std::map<class std::basic_string_view<char,struct std::char_traits<char> >,unsigned int,struct std::less<class std::basic_string_view<char,struct std::char_traits<char> > >,class std::allocator<struct std::pair<class std::basic_string_view<char,struct std::char_traits<char> > const ,unsigned int> > > >(class std::map<class std::basic_string_view<char,struct std::char_traits<char> >,unsigned int,struct std::less<class std::basic_string_view<char,struct std::char_traits<char> > >,class std::allocator<struct std::pair<class std::basic_string_view<char,struct std::char_traits<char> > const ,unsigned int> > > &,unsigned char)" (??$?RV?$map@V?$basic_string_view@DU?$char_traits@D@std@@@std@@IU?$less@V?$basic_string_view@DU?$char_traits@D@std@@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@std@@@std@@I@std@@@2@@std@@@map_manip@@QAEXAAV?$map@V?$basic_string_view@DU?$char_traits@D@std@@@std@@IU?$less@V?$basic_string_view@DU?$char_traits@D@std@@@std@@@2@V?$allocator@U?$pair@$$CBV?$basic_string_view@DU?$char_traits@D@std@@@std@@I@std@@@2@@std@@E@Z) referenced in function _main
serialization.exe : fatal error LNK1120: 1 unresolved externals

Honestly, I do not get this error at all, but it seems like it’s somehow connected to the auto. Even though changing auto to template does not change a thing, if we remove auto& map from void operator() arguments (both database.h and database.cpp), then it compiles to .exe just fine!


Compiling with c++20 and moving #include <string> from serialization.cpp => database.h

database.h:

#pragma once

#include <map>
#include <string>

struct map_manip 
{
    void operator()(auto& map, uint8_t size = 2);
};

serialization.cpp:

#include "database.h"

struct entry
{
    std::map<std::string_view, uint32_t> units;
};

int main()
{
    entry x;
    map_manip y;
    y(x.units);
}

In this case I just get an internal compiler error. It feel I should report this to MSVC developers but still provide it here as well, just in case.

D:devLocalTest>cl /EHsc /std:c++20 serialization.cpp database.cpp
Microsoft (R) C/C++ Optimizing Compiler Version 19.29.30133 for x86
Copyright (C) Microsoft Corporation.  All rights reserved.

serialization.cpp
serialization.cpp(5): fatal error C1001: Internal compiler error.
(compiler file 'msc1.cpp', line 1603)
 To work around this problem, try simplifying or changing the program near the locations listed above.
If possible please provide a repro here: https://developercommunity.visualstudio.com
Please choose the Technical Support command on the Visual C++
 Help menu, or open the Technical Support help file for more information
INTERNAL COMPILER ERROR in 'C:devMicrosoft Visual Studio2019CommunityVCToolsMSVC14.29.30133binHostX86x86cl.exe'
    Please choose the Technical Support command on the Visual C++
    Help menu, or open the Technical Support help file for more information

Any ideas would be hugely appreciated.

Answer

  1. auto in function parameter list makes an abbreviated function template, a C++20 feature
  2. As the function is template, you need to move the function definition to header, as usual with templates, to make the program link; see Why can templates only be implemented in the header file?
  3. Report ICE to https://developercommunity.visualstudio.com/home or via Help > Send Feedback > Report a problem… from Visual Studio