与 MSVC 链接错误,但与 constexpr 的 g++ 无关

Posted

技术标签:

【中文标题】与 MSVC 链接错误,但与 constexpr 的 g++ 无关【英文标题】:Link error with MSVC but not with g++ with constexpr 【发布时间】: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他们已经内联了。 【参考方案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 诊断是编译器向您提供的有关您所做的不好的事情的消息(可能是错误,也可能是警告)。通常,编译器需要向您提供有关您做错的事情的消息。但有时,实际上很难弄清楚这一点——因此该标准不需要诊断。这是其中一种情况。

以上是关于与 MSVC 链接错误,但与 constexpr 的 g++ 无关的主要内容,如果未能解决你的问题,请参考以下文章

constexpr 在联合中初始化结构时,msvc visual c++ 静默错误代码生成

为啥从 constexpr 引用生成的汇编代码与 constexpr 指针不同?

为什么std :: count比MSVC编译器的循环慢,但与GCC相等?

C++ constexpr类型说明符

由于不同版本的 MSVC 和 Qt 库导致链接错误

constexpr string_view 比较