【发布时间】:2021-09-10 03:07:29
【问题描述】:
据我所知,一个很常见的情况是这样的
template<int i> class Class
{
public:
static constexpr int I = i;
static constexpr int J = constexprFunction(i);
// further Class implementation
};
几乎和我一样常见的错误是(事实上,我在这里的大部分问题都是因为我忘记了它并且不知道正确的问题是什么)如果成员被 odr-used 忘记了附加定义:
template<int i> constexpr int Class<i>::I;
template<int i> constexpr int Class<i>::J;
现在我读到了cppreference: Definitions and ODR 和cppreference: static members,它们声明这对于 C++17 已弃用。这对我来说似乎很棒,因为它避免了很多错误。但是还有其他问题:
1) 除了使附加定义无用之外,这种变化还有其他原因吗? (另请参阅此问题的最后一段)
2) 在cppreference: static members 的最后一个示例中,它似乎也适用于const static 成员-但规则仅声明constexpr 成员。是否适用于const static 会员?
3) 我发现的所有示例都使用了像 Class::I 这样的简单定义 - 这是否也适用于 Class:J 的情况以及 constexpr 函数?
简要说明 C++17 之前和 C++17 的最佳实践是什么。总而言之,这对我来说似乎是一个非常棘手的变化,因为它会使很多以前“格式错误的非诊断要求”的代码变成好的代码(据我所知......)。因此,将产生代码,使用旧的(17 之前的)编译器仍然是“格式错误的非诊断要求” - 但只要不需要使用 odr,这些都不会抱怨。
编辑:更正了 Aaron McDaid 建议的文字。
【问题讨论】:
-
我认为关于静态数据成员的最后一个示例是编辑错误(现已修复):9.2.3.2[class.static.data]p3 说,对于“非易失性非内联 const 静态数据member", "如果成员被 odr-used,则仍应在命名空间范围内定义"
-
我对当前问题中的文字感到困惑:“如果成员被 odr-used,则错误...给出定义”。当然,您的意思是,例如在 C++11 中,fail 给出定义是错误的吗?你忘了否定吗? (对不起,如果这看起来很迂腐,但我真的不太了解这一点,无法确定这里的意图)
-
@AaronMcDaid 是的,这是真的。我修好了它。我明确表示有必要在 C++11 中给出附加定义,但在 C++17 中不再如此。因此,我试图在最后一段中解释我对向下兼容目的的困惑。
-
@Cubbi:有没有可能,这个功能还没有在 gnu 编译器中实现?我用this question的MWE试了一下,用
g++-6和-std=C++17编译。它仍然抱怨缺乏定义!还是我在想一些愚蠢的事情? -
@marlam 这个功能甚至没有在 gcc compliance status table 中列出。它在clang 3.9 中可用。它也可以在 MSVC 2015 中使用(尽管在这种情况下是因为缺乏标准)
标签: c++ static constexpr c++17