简体   繁体   中英

Link error with MSVC but not with g++ with constexpr

Consider the following code:

#include <iostream>

struct FactoryTag
{
    static struct Shape {} shape;
    static struct Color {} color;
};

template <typename TFactory>
int factoryProducer(TFactory tag)
{
    if constexpr (std::is_same<TFactory, FactoryTag::Shape>::value)
        return 12;
    else if constexpr (std::is_same<TFactory, FactoryTag::Color>::value)
        return 1337;
}

int main()
{
    std::cout << factoryProducer(FactoryTag::shape) << std::endl;
    return 0;
}

It works fine with g++ -std=c++1z Main.cpp but in Visual Studio with MSVC set with c++17 support it gives

Error   LNK2001 unresolved external symbol "public: static struct FactoryTag::Shape FactoryTag::shape" (?shape@FactoryTag@@2UShape@1@A) StaticTest  C:\Users\danielj\source\repos\StaticTest\StaticTest\StaticTest.obj  1   

Is this a bug in MSVC?

Is this a bug in MSVC?

No, FactoryTag::shape is odr-used here, so it needs a definition (you're copy-constructing it, which goes through the implicitly generated copy constructor, which requires you to bind a reference). Nor is this a bug in gcc either, arguably, since there is no diagnostic required if a definition is missing.

The solution is to add a definition. The old way would be:

struct FactoryTag { ... };

Shape FactoryTag::shape{}; // somewhere in a source file

The new way would be:

struct FactoryTag {
    struct Shape {} static constexpr shape {}; // implicitly inline in C++17
};

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM