无法在 C++ 中将类方法指定为 constexpr

问题描述 投票:0回答:1

我正在使用 constexpr 函数(字符串 -> NFA -> DFA)用 C++ 编写一个简单的编译时正则表达式解析器。但是,我无法将我的一些类方法设置为 constexpr。我尝试了各种组合,但似乎我必须实现我自己的

std::shared_ptr
版本,它是每个成员函数的 constexpr 。

有人可以帮我吗?这似乎是一个微不足道的问题,因为

new
delete
现在有 constexpr 支持,但我仍然无法声明我的方法 constexpr。这是代码:

#include <memory>
#include <variant>
#include <iostream>
#include <utility>
#include <cstdint>
#include <vector>
#include <bit>
#include <source_location>
#include <array>
#include <string_view>
#include <algorithm>
#include <type_traits>
#include <limits>

struct Node
{
private:
    friend class NodeManager;
    std::size_t unique_index{ std::numeric_limits<std::size_t>::max() };
public:
    std::vector<std::shared_ptr<Node>> empty_transitions{};
    std::vector<std::pair<std::string, std::shared_ptr<Node>>> tran_nodes{};
};

class NodeManager
{
public:
    constexpr NodeManager() = default;
    constexpr NodeManager(const NodeManager&) = delete;
    constexpr NodeManager(NodeManager&&) = delete;
    constexpr NodeManager& operator=(const NodeManager&) = delete;
    constexpr NodeManager& operator=(NodeManager&&) = delete;

    std::vector<std::shared_ptr<Node>> all_nodes;

    constexpr auto create_node() -> std::shared_ptr<Node>
    {
        all_nodes.emplace_back(std::make_shared<Node>());
        all_nodes.back()->unique_index = all_nodes.size() - 1;
        return all_nodes.back();
    }

    constexpr auto get_node_count() const
    {
        return all_nodes.size();
    }

    constexpr void delete_node(std::shared_ptr<Node> node)
    {
        auto index = std::exchange(node->unique_index, std::numeric_limits<std::size_t>::max());
        all_nodes[index] = nullptr;

        if (index != all_nodes.size() - 1)
        {
            std::swap(all_nodes[index], all_nodes.back());
            all_nodes[index]->unique_index = index;
        }

        all_nodes.pop_back();
    }

    constexpr void garbage_collect()
    {
        for (int i = 0; i < all_nodes.size(); ++i)
        {
            if (all_nodes[i].use_count() > 1)
                continue;

            delete_node(all_nodes[i]);
        }
    }

    constexpr void delete_all_nodes()
    {
        all_nodes.clear();
    }
};

constexpr auto foo()
{
    auto ptr = NodeManager().create_node();
    return 5;
}

int main()
{
    constexpr auto x = foo();
    return 0;
}

这是我收到的编译错误:

example.cpp
<source>(36): error C3615: constexpr function 'NodeManager::create_node' cannot result in a constant expression
<source>(36): note: failure was because type 'std::shared_ptr<Node>' is not a literal type
C:/data/msvc/14.39.33321-Pre/include\memory(1649): note: type 'std::shared_ptr<Node>' is not a literal type because it has a user-defined destructor
<source>(39): note: failure was caused by call of undefined function or one not declared 'constexpr'
<source>(39): note: see usage of 'std::shared_ptr<Node>::operator ->'
<source>(40): note: failure was caused by call of undefined function or one not declared 'constexpr'
<source>(40): note: see usage of 'std::shared_ptr<Node>::shared_ptr'
<source>(48): error C3615: constexpr function 'NodeManager::delete_node' cannot result in a constant expression
<source>(48): note: failure was because type 'std::shared_ptr<Node>' is not a literal type
C:/data/msvc/14.39.33321-Pre/include\memory(1649): note: type 'std::shared_ptr<Node>' is not a literal type because it has a user-defined destructor
<source>(51): note: failure was caused by call of undefined function or one not declared 'constexpr'
<source>(51): note: see usage of 'std::shared_ptr<Node>::operator ='
<source>(87): error C2131: expression did not evaluate to a constant
<source>(81): note: function violates 'constexpr' rules or has errors
<source>(81): note: see usage of 'NodeManager::create_node'
<source>(87): note: the call stack of the evaluation (the oldest call first) is
<source>(87): note: while evaluating function 'int foo(void)'
<source>(81): note: while evaluating function 'std::shared_ptr<Node> NodeManager::create_node(void)'
Compiler returned: 2

Godbolt 链接:https://godbolt.org/z/YbsrferP6

谢谢!

c++ c++20 shared-ptr constexpr
1个回答
0
投票

编译器错误告诉你出了什么问题:

<source>(40): note: failure was caused by call of undefined function or one not declared 'constexpr'
<source>(40): note: see usage of 'std::shared_ptr<Node>::shared_ptr

shared_ptr 不是 constexpr(有关 make_shared 和 shared_ptr,请参阅 cppreference)。 unique_ptr 可以用于 constexpr,但仅从 c++23 开始。我不确定operator new是否可以在c++20中使用constexpr,我认为这也需要c++23?

无论哪种方式,即使你可以切换到c++23,你也需要使用unique_ptr而不是shared_ptr。

© www.soinside.com 2019 - 2024. All rights reserved.