派生类中的表达,clang vs rest

时间:2018-04-27 15:27:41

标签: c++ gcc clang

最小例子:

#include <cstddef>
struct B
{
    constexpr static const size_t MAX = 10;
};

struct D : B 
{
    constexpr static const size_t MAX = 20;
};

void use(const B& v)
{
    static_assert(v.MAX == 10, "");
}

template<typename X>
void use2(X&& v)
{
    static_assert(v.template MAX == 20, "");
}

int main ()
{
    D d;
    static_assert(d.MAX == 20, "");
    use(d);
    use2(d);

    return 0;
}

GCC(v5.4 ... v7.3):编译好(任何级别的优化和-Wall -Wextra -pedantic) ICC / MSVC:编译好(在godbolt.org上尝试各种版本)

CLANG(v4 ... v6):错误:static_assert表达式不是整数常量表达式         static_assert(v.MAX == 10,“”);

编辑(改写问题):

在我看来,clang的行为是最不令人惊讶的(或更直观)。鉴于它是唯一没有编译上述代码的编译器,我想了解这两种行为中的哪一种是正确的以及为什么?

编辑2:

通过添加模板函数判断,gcc看起来使用参数的声明类型,并确定使用哪个constexpr成员,而不管传入的是什么。

如果通过值,clang也会将MAX评估为常量表达式。在这种情况下,很明显为什么v.MAX == 10对于非模板化函数的所有编译器都是正确的。

编辑3(甚至更短的版本): 哪个仍然无法在clang上编译

#include <cstddef>

struct B
{
     constexpr static const size_t MAX = 10;
};

void use(const B& v)
{
    static_assert(v.MAX == 10, "");
}

template<typename X>
void use2(X&& v)
{
    static_assert(v.template MAX == 10, "");
}

int main ()
{
    B v;
    static_assert(v.MAX == 10, "");
    use(v);
    use2(v);

    return 0;
}

1 个答案:

答案 0 :(得分:2)

Clang是对的。

import os, subprocess fileToRemove = '/home/user/fileName'; if os.path.isfile(fileToRemove): subprocess.run(['rm', '-f', '--preserve-root', fileToRemove] subprocess.run(['safe-rm', '-f', fileToRemove] 评估v.MAX == 10,这是没有先前初始化的引用。在常量表达式中不允许这样做。

请注意,即使v是静态成员,MAX评估期间仍会评估v

您可以使用班级类型访问v.MAX以避免评估MAX,例如

v