【问题标题】:Undefined Reference in inline function, solved with unary +内联函数中的未定义引用,用一元 + 解决
【发布时间】:2014-03-10 18:33:42
【问题描述】:

我在启用 c++11 时遇到了一个奇怪的 gcc 4.7 问题:

当我想编译这个时:

constexpr unsigned int getDim(const int e){
        return (e==1)?  A::Set::Dimension :
            (
              (e==2)? B::Set::Dimension :

                (
                    (e==3)? C::Set::Dimension :
                    (
                       +D::Set::Dimension

                    )
                )
            );
 }

对于每个结构 A,B,C,D,其中定义了 Set 的 typedef,其中相关 Set 具有 int Dimension,例如

struct SetOne{
   static const int Dimension = 1;
}

struct A{
   typedef SetOne Set;
}

如果我不使用 D::Set::Dimension 前面的 unary +,链接器将无法抱怨对 SetOne::Dimension 的未定义引用。

这是不是和Undefined reference to static class member一样的问题

我不能给出 MWE,因为对于一个 .cpp 文件的简单示例,问题就消失了。 ? (但 A、B、C、D 的所有定义都在一个头文件中)

有人知道这里可能出了什么问题吗?这是不直观的:-)

观察 2: 如果将:+D::Set::Dimension 替换为 0,则编译正常,但为什么将其他语句破解为 A::Set::Dimension 不会出现相同的链接错误?

【问题讨论】:

  • 是的,您对先前回答的问题的假设似乎是正确的。 static const int Dimension = 1; 内部类声明只是一个静态变量声明,而不是定义(尽管初始化)。您应该在声明之外显式定义类的静态成员。
  • 如果我在 cpp 文件中定义类声明之外的静态成员,那么我不能在模板函数f<Set::Dimension> 中使用静态 int,因为编译器需要查看 const 表达式...?我怎样才能避免这种情况?
  • 如果您仅将整型静态变量用于此类目的,您可以在类中初始化它们并在类之外创建它们的定义而无需任何初始化。 初始化和定义不一样。如果你会使用C++11你也可以尝试使用constexpr关键字。

标签: c++ c++11 static linker


【解决方案1】:

在您正在构建的表达式中,三元表达式产生一个左值,这会导致静态常量的odr-use。单一定义规则要求odr-used 的所有静态成员都是已定义,因此您需要提供定义(在单个翻译单元中)。

那么为什么问题会随着一元 + 消失?

一元+不会导致静态成员的odr-use,它只需要一个rvalue,它的结果是另一个右值。这通过条件运算符级联,因为一旦两个参数之一是 rvalue,表达式的结果也将是 rvalue。最终结果是单个+ 具有强制函数中使用的所有静态常量的左值到右值转换的效果,并删除了odr-uses em>。

如果将 +D::Set::Dimension 替换为 0,则编译正常

同样,0 是一个右值,它与上面描述的一元+ 具有相同的效果。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-10-28
    • 2013-10-04
    • 2013-02-14
    • 1970-01-01
    • 2019-04-13
    • 2012-01-26
    • 1970-01-01
    • 2017-06-27
    相关资源
    最近更新 更多