【问题标题】:Is it illegal get `sizeof` non-static member of struct nested within class template?获取嵌套在类模板中的结构的“sizeof”非静态成员是否非法?
【发布时间】:2016-06-24 10:00:51
【问题描述】:

在clang/llvm 3.6.2中,使用std=c++11编译时,以下代码会导致编译错误:

template <typename T=void>
class bar
{
public:
    struct foo
    {
        int array[10];
    };

    int baz()
    {
        return sizeof(foo::array);
    }
};

int main(void)
{
    bar<> b;
    return b.baz();
}

命令行调用:

$ clang++ -std=c++11 nonstatic.cpp -o nonstatic
nonstatic.cpp:12:28: error: invalid use of non-static data member 'array'
        return sizeof(foo::array);
                      ~~~~~^~~~~
nonstatic.cpp:20:14: note: in instantiation of member function
'bar<void>::baz' requested here
    return b.baz();

如果我将bar 更改为不再是模板,如

class bar
{
public:
    struct foo
    {
        int array[10];
    };

    int baz()
    {
        return sizeof(foo::array);
    }
};

int main(void)
{
    bar b;
    return b.baz();
}

然后代码编译干净。值得注意的是,GCC 5.2.1 接受std=c++11 下的两个版本。另外值得注意的是,将 array 移动到封闭类模板主体(但将其保留为模板)也会导致 clang 接受这一点。

相对于标准,哪种行为是正确的?这是 GCC、clang 中的错误,还是两者都有?

(我在 cfe-users 上问过同样的question,但到目前为止没有收到任何回复)。

【问题讨论】:

  • 看起来像一个 clang++ 错误。等待大师确认。
  • 是的,当然是一个错误。
  • stackoverflow.com/questions/29359661/… 中提到的解决方法sizeof(((foo*) 0)-&gt;array) 也适用于此。

标签: c++11 gcc clang language-lawyer clang++


【解决方案1】:

这肯定是一个clang错误; sizeof 表达式的操作数是一个 id-expression 表示非静态数据成员,因此 [expr.prim.general]/13 成立。这是一个简化的示例:

template<class T> struct M { int f() { return sizeof(T::x); } };
struct S { int x; };
int main() { return M<S>{}.f(); }

当在模板实例方法内的未评估上下文中访问依赖类型成员时会出现该错误。 Clang 对n2253 rule enabling the use of non-static data members in unevaluated context(以及后来的改进)的实现显得相当脆弱,并且与模板的交互很糟糕; http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20151019/141535.html 是一个类似(虽然不同)的错误。

我找不到任何迹象表明这已经报告给Clang Bugzilla;您可能想打开一个新错误。

根据您的情况,解决方法可能包括将静态类型和值计算移到实例方法之外;值得注意的是,即使将 baz 设为 static 成员函数也足以说服 clang 接受您的代码。

【讨论】:

  • 感谢您的回复。我将继续向 Clang bugzilla 提交一个错误。我的用例将数组的长度作为模板参数之一的(简单)函数,所以我很容易使用它而不是调用sizeof
猜你喜欢
  • 2021-10-06
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
  • 2017-01-15
  • 1970-01-01
  • 2019-10-11
  • 1970-01-01
相关资源
最近更新 更多