Constexpr使用C ++ 17查找数组

时间:2018-06-30 10:48:35

标签: c++ arrays c++17 constexpr

我正在尝试编写constexpr查找函数,该函数将返回包含特定值的std :: array的索引。除非包含的类型为const char*,否则下面的函数似乎可以正常工作:

#include <array>

constexpr auto name1() {
    return "name1";
}

constexpr auto name2() {
    return "name2";
}

template <class X, class V>
constexpr auto find(X& x, V key) {
    std::size_t i = 0;
    while(i < x.size()) {
        if(x[i] == key) return i;
        ++i;
    }

    return i;
}


int main() {

    constexpr std::array<const char*, 2> x{{name1(), name2()}};
    constexpr auto f1 = find(x, name1()); // this compiles
    constexpr auto f2 = find(x, name2()); // this doesn't...
}

奇怪的是find(x, name1())可以干净地编译,但是find(x, name2())失败并显示以下错误:

subexpression not valid in a constant expression
        if(x[i] == key) return i; `

name1()一起使用时该表达式如何工作,而与name2()一起使用时如何失败?

我也找到了这个answer,但是用户从头开始构建数组类,而我不想这样做。

1 个答案:

答案 0 :(得分:3)

似乎是编译器错误。 f1f2都应该以相同的方式编译。

主要问题是,这是"name1" == "name1""name1" != "name2"假设。该标准实际上不提供此类保证,请参见[lex.string]/16

  

所有字符串文字是否都是不同的(即存储在不重叠的对象中),并且不确定string-literal的连续求值是产生相同对象还是不同对象。

即使最有可能成立该假设,也明确不允许比较constexpr中未指定的值,请参见[expr.const]/2.23

  

-关系([expr.rel])或等式([expr.eq])运算符,其结果未指定;

一种解决方法(正确的做法)是不依赖字符串文字的地址,而是比较实际的字符串。例如:

constexpr bool equals(const char* a, const char* b) {
    for (std::size_t i = 0; ; ++i) {
        if (a[i] != b[i]) return false;
        if (a[i] == 0) break;
    }
    return true;
}

template <class X, class V>
constexpr auto find(X& x, V key) {
    std::size_t i = 0;
    while(i < x.size()) {
        if(equals(x[i], key)) return i;
        ++i;
    }

    return i;
}