获取嵌套在 class 模板中的结构的 `sizeof` 非静态成员是否非法?

Is it illegal get `sizeof` non-static member of struct nested within class template?

在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 移动到封闭的 class 模板主体中(但将其保留为模板)也会导致 clang 接受这个。

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

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

这肯定是一个 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 (and later improvements) appears rather fragile and to interact badly with templates; a similar (though distinct) bug is http://lists.llvm.org/pipermail/cfe-commits/Week-of-Mon-20151019/141535.html.

的实现

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

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