Search code examples
c++templatesgccvisual-c++variadic-templates

Nested template (C++17) compilation fails on VS19


Code:

(Note that template is not instantiated - that's not a mistake, compilation fails even without it) main.cpp:

namespace mylib {
    template<typename ...Params>
    class SomeClass {
        public:
            template<typename ...NestedParams>
            class NestedClass {
            };

            template<typename ...NestedParams>
            NestedClass<NestedParams...> createNestedInstance();
    };
}

template<typename... Params>
template<typename... NestedParams>
typename mylib::SomeClass<Params...>::template NestedClass<NestedParams...>
mylib::SomeClass<Params...>::createNestedInstance() {
    return SomeClass::NestedClass<NestedParams...>();
}

CMakeLists.txt

cmake_minimum_required(VERSION 3.17)
project(msvc_exploit001)

set(CMAKE_CXX_STANDARD 17)

add_library(msvc_exploit001 main.cpp)

GCC (Msys64 MinGW64): compiles without warnings

Visual Studio Comminity 2019:

msvc_exploit001.cpp(25): error C2244: 'mylib::SomeClass<Params...>::createNestedInstance': unable to match function definition to an existing declaration
msvc_exploit001.cpp(25): note: see declaration of 'mylib::SomeClass<Params...>::createNestedInstance'
msvc_exploit001.cpp(25): note: definition
msvc_exploit001.cpp(25): note: 'mylib::SomeClass<Params...>::NestedClass<NestedParams...> mylib::SomeClass<Params...>::createNestedInstance(void)'
msvc_exploit001.cpp(25): note: existing declarations
msvc_exploit001.cpp(25): note: 'mylib::SomeClass<Params...>::NestedClass<NestedParams...> mylib::SomeClass<Params...>::createNestedInstance(void)'
NMAKE : fatal error U1077: 'C:\PROGRA~2\MICROS~4\2019\COMMUN~1\VC\Tools\MSVC\1427~1.291\bin\Hostx64\x64\cl.exe' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.
NMAKE : fatal error U1077: '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Tools\MSVC\14.27.29110\bin\HostX64\x64\nmake.exe"' : return code '0x2'
Stop.

Printed by MSVC error contains identical signatures for both declaration and definition, but it insists that they do not match.

I'm compiling on Windows 10, using CMake (CLion) and default compiler options (only specifying C++17 standard level)


Solution

  • It seems msvc has issues with the template. This compiles

    namespace mylib {
        template<typename ...Params>
        class SomeClass {
            public:
                template<typename ...NestedParams>
                class NestedClass {
                };
    
                template<typename ...NestedParams>
                NestedClass<NestedParams...> createNestedInstance();
        };
    }
    
    template<typename... Params>
    template<typename... NestedParams>
    typename mylib::SomeClass<Params...>::NestedClass<NestedParams...>
    mylib::SomeClass<Params...>::createNestedInstance() {
        return SomeClass::NestedClass<NestedParams...>();
    }
    
    int main() {
        auto sc = mylib::SomeClass<int, bool>();
        auto c = sc.createNestedInstance<float, double>();
    }
    

    As stated in the comments, the template might be required by the standard. In that case, maybe you should file a bug report at Microsoft.