static_assert和Intel C++编译器

Rus*_*pov 8 c++ static-assert icc visual-c++

阅读cppreference.com:

静态断言声明可能出现在块作用域(作为块声明)和类体内(作为成员声明)

好的,现在我有以下代码:

struct foo_t
{
    static constexpr std::size_t maxAlignment()
    {
        // This is just a sample; I removed real code from this method.
        return std::max(alignof(__m128), __alignof(__m256));
    }

    static_assert(0 == ((maxAlignment() -1) & maxAlignment()), "some message");
};
Run Code Online (Sandbox Code Playgroud)

MSVC 2015和Intel C++ 16.0.2都没有编译此代码(前者显示"错误C2131:表达式未评估为常量",后者显示"函数调用必须在常量表达式中具有常量值"错误并指向调用maxAlignmentin static_assert).

但MSVC 2015 Update 1 确实编译了以下代码,而英特尔C++ 16.0.2 则没有:

template <typename T, std::size_t Alignment>
struct foo_t
{
    static constexpr std::size_t maxAlignment()
    {
        return std::max(std::alignment_of<T>::value, Alignment);
    }

    static_assert(0 == ((maxAlignment() -1) & maxAlignment()), "some message");
};

foo_t<__m128, 16> foo {};
// foo_t<__m128, 33> boo {};  // here `static_assert` will stop compilation
Run Code Online (Sandbox Code Playgroud)

(所以,MSVC可以处理static_assert它在模板类体内的时间)

但是下面的代码由两个编译器成功编译(static_assert在类体之外;它出现在块范围内):

struct foo_t
{
    static constexpr std::size_t maxAlignment()
    {
        return std::max(alignof(__m128), __alignof(__m256));
    }
};

static_assert(0 == ((foo_t::maxAlignment() -1) & foo_t::maxAlignment()), "some message");
Run Code Online (Sandbox Code Playgroud)

我的问题是:我错过了什么或是英特尔C++编译器的错误?

ixS*_*Sci 1

如果我没记错的话,constexpr 函数在完全定义之前不能使用,并且类成员 constexpr 函数在类定义之前未定义,这意味着您不能在定义的类范围内使用 constexpr 成员static_assert函数正是这个功能。

但是你可以使这个函数独立(无论如何它已经是静态的)并且它会完成这项工作。它应该在任何地方编译。