c++ - 错误 : 'this' is not a constant expression

标签 c++ templates c++14 c++17 constexpr

我有带有 constexpr 方法的 constexpr 对象构造函数。

// My SparseArray implementation

#include <cstdint>
#include <iostream>
#include <utility>

template<typename T, uint64_t size>
class SparseArray 
{
    public:
    using ElementType = T;

    template<typename... Args>
    constexpr SparseArray(Args&&... args) 
    : values{args...} {
        std::cout << "Args ctor." << '\n';
    }

    template<uint8_t Index>
    constexpr ElementType get() const {
        // some logic
        return T();
    }

    constexpr auto someMethod() {
        get<0>();                                            // <--------- works fine
        auto seq  = std::integer_sequence<ElementType, 0>{}; // <--------- works fine
        auto seq2 = std::integer_sequence<ElementType, get<0>()>{}; // <-- error
    }

    ElementType values[size];  
};

int main ()
{
    SparseArray<int, 3> array(1, 2, 3);
    array.someMethod();

    return 0 ;
}

Run code

但我确实需要在这样的编译时上下文中使用方法。 我要在编译时对两个 constexpr 对象求和,因此我需要使用 get 方法获取两者的数据。

=======已编辑=====

@chris 回答后,我明白我错过了一件事。 实际上 get 方法是这样的:

    template<uint8_t Index>
    constexpr ElementType get() const {
        if(/*some logic*/)
            return values[/*some logic*/];
        else
            return T();
    }

因此,代码处理对象的数据成员。

最佳答案

constexpr 函数必须在编译时和运行时可用。您正在调用一个非静态成员函数,因此无论类对象在编译时是否已知,它都需要工作。如果您需要在编译时知道该对象,则该函数在运行时不再有效。

解决此问题的最简单方法是使用不依赖于未使用的类对象的函数:

template<uint8_t Index>
static constexpr ElementType get() {
    // some logic
    return T();
}

如果这不是一个选项,因为您正在使用类对象,那么您需要确保该对象是 constexpr 才能使用它:

constexpr SparseArray<int, 3> array(1, 2, 3);
auto seq2 = std::integer_sequence<int, array.get<0>()>{};

无论您在何处使用 get,结果可用作编译时值的唯一方法是所有参数(包括对象)都是编译时值。

EWG 已接受 constexpr!强制对函数进行编译时评估,但在与 constexpr SparseArray 对象一起使用之前,它不会使您的原始示例编译。

关于c++ - 错误 : 'this' is not a constant expression,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51152012/

相关文章:

c++ - 用 cin 缓冲区做东西直到空

c++ - VC编译C++模板代码时如何设置更严格的编译规则

c++ - std::string 中的非法指令

c++ - 如何重载 << 运算符以使用模板函数将元素添加到 vector 中? (c++)

c++ - 部分或完全匹配类型参数包

c++ - 如何在 hpp 中声明一个 vector ?

c++ - 如何声明函数 vector (lambda)

c++ - Qt Creator - 如何为 ubuntu linux 设置应用程序图标?

c++ - 要获得引用计数,我是否必须使用 shared_ptr 来混淆我的 API?

c++ - 将 vector 复制到 STL 中的列表的最佳方法?