【问题标题】:using std::max causes a link error?使用 std::max 会导致链接错误?
【发布时间】:2017-12-16 03:02:16
【问题描述】:

考虑一个在头文件中定义的库

struct Proj {
    struct Depth {
        static constexpr unsigned Width = 10u;
        static constexpr unsigned Height = 10u;
    };
    struct Video {
        static constexpr unsigned Width = 10u;
        static constexpr unsigned Height = 10u;
    };
};

该库已编译,我现在正在开发一个链接到该库的应用程序。我想了很长时间,这是某种可见性问题,但即使在到处添加B_EXPORT(CMake 中的标准可见性东西)没有任何变化后,我终于找到了问题。

template <class Projection>
struct SomeApplication {
    SomeApplication() {
        unsigned height = std::max(// or std::max<unsigned>
            Projection::Depth::Height,
            Projection::Video::Height
         );
    }
};

我什至无法使用小型虚拟库/示例应用程序重现该问题。但是在应用程序中使用std::max会导致链接错误,而如果我只是自己做的话

unsigned height = Projection::Depth::Height;
if (height < Projection::Video::Height)
    height = Projection::Video::Height;

一切顺利。 AKA 仅使用 Projection::XXX 的可见性似乎没有任何具体问题。

对可能导致这种情况的任何想法?这是在 OSX 上,所以this doesn't even apply

【问题讨论】:

    标签: c++11


    【解决方案1】:

    问题在于WidthHeight声明的,而不是在您的structs 中定义。实际上,这意味着没有为它们分配存储空间。

    现在回忆std::max的签名:

    template<typename T>
    const T& max(const T&, const T&);
    

    注意引用:这意味着要获取参数的地址。但是,由于 WidthHeight 仅被声明,它们没有任何存储空间!因此链接器错误。

    现在让我们考虑您的其余问题。

    您手写的max 有效,因为您从不使用任何指针或变量引用。

    您可能无法在玩具示例中重现这一点,因为特别取决于优化级别,足够智能的编译器可能会在编译时评估 max 并省去在运行时获取地址的麻烦。例如,比较 gcc 7.2 的 no optimization-O2 的 disasm:评估确实是在编译时完成的!

    至于修复,这取决于。您有多种选择,仅举几例:

    1. 使用 constexpr getter 函数代替变量。在这种情况下,它们返回的值将更像临时对象,允许获取地址(编译器肯定会优化它)。这是我一般建议的方法。
    2. 使用命名空间而不是结构。在这种情况下,除了声明变量之外,还将定义变量。需要注意的是,如果在多个翻译单元中使用它们,您可能会遇到重复的符号错误。解决此问题的方法仅是 C++17 内联变量。
    3. ...说起来,C++17 也改变了 constexpr 静态成员变量的规则(默认变为内联),所以只要切换到这个标准就不会出现这个错误。

    【讨论】:

    • 哇!如此清晰,深思熟虑的答案很有意义 - 感谢您如此仔细地解释它!我将不得不使用 1,我的项目的依赖项需要 C++11,并且这个 Proj 类被用作许多其他可能的预测之一。保持它们自包含允许框架的其余部分由struct 定义。我期待继续使用 C++17,这是(又一个)这样做的原因
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-24
    相关资源
    最近更新 更多