【问题标题】:Link error with MSVC but not with g++ with constexpr与 MSVC 链接错误,但与 constexpr 的 g++ 无关
【发布时间】:2018-09-25 14:57:06
【问题描述】:

考虑以下代码:

#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;
}

它适用于g++ -std=c++1z Main.cpp,但在 Visual Studio 中设置了 MSVC 并支持 c++17,它提供了

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   

这是 MSVC 中的错误吗?

【问题讨论】:

  • 您可以使用static inline constexpr struct Shape {} shape{}; static inline constexpr struct Color {} color{}; 解决此问题,即为这些静态成员提供定义。
  • @VTT,你不需要inline,因为constexpr他们已经内联了。

标签: c++ gcc visual-c++ c++17


【解决方案1】:

这是 MSVC 中的错误吗?

不,FactoryTag::shape 在这里是 odr-used 的,所以它需要一个定义(你正在复制构造它,它通过隐式生成的复制构造函数,这需要你绑定一个参考)。可以说,这也不是 gcc 中的错误,因为如果缺少定义,则会出现 no diagnostic required

解决方案是添加定义。旧方法是:

struct FactoryTag { ... };

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

新方法是:

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

【讨论】:

  • 我不太明白“无需诊断”是什么意思?
  • @J.Daniel 诊断是编译器向您提供的有关您所做的不好的事情的消息(可能是错误,也可能是警告)。通常,编译器需要向您提供有关您做错的事情的消息。但有时,实际上很难弄清楚这一点——因此该标准不需要诊断。这是其中一种情况。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-07-18
  • 1970-01-01
  • 1970-01-01
  • 2018-06-22
  • 2012-09-19
相关资源
最近更新 更多