VAR在其自己的初始化器中使用

var used in its own initializer

本文关键字:初始化 自己的 VAR      更新时间:2023-10-16

以下代码:

    auto getConnection(const std::string &name) {
        constexpr const std::size_t id{findFactoryId(_factories, name)};
        const auto factory = std::get<std::integral_constant<std::size_t, id>{}>(_factories).second;
        for (auto &connection : _connections[id])
            if (connection.first) {
                connection.first = false;
                decltype(factory()) &res = std::experimental::any_cast(connection.second);
                return res;
            }
        _connections[id].emplace_back(std::make_pair<bool, std::experimental::any>(false, factory()));
        decltype(factory()) &res = std::experimental::any_cast(_connections[id].back().second);
        return res;
    }

用clang 编译,但使用G 给出了此错误:

In file included from main.cpp:2:0:
src/core/include/connectionpool.h: Dans la fonction membre « auto Core::ConnectionPool<Connectors>::getConnection(const string&) »:
src/core/include/connectionpool.h:28:79: erreur : the value of « id » is not usable in a constant expression
             const auto factory = std::get<std::integral_constant<std::size_t, id>{}>(_factories).second;
                                                                               ^~
src/core/include/connectionpool.h:27:41: note : « id » used in its own initializer
             constexpr const std::size_t id{findFactoryId(_factories, name)};
                                         ^~
src/core/include/connectionpool.h:28:81: erreur : the value of « id » is not usable in a constant expression
             const auto factory = std::get<std::integral_constant<std::size_t, id>{}>(_factories).second;
                                                                                 ^
src/core/include/connectionpool.h:27:41: note : « id » used in its own initializer
             constexpr const std::size_t id{findFactoryId(_factories, name)};
                                         ^~
src/core/include/connectionpool.h:28:81: note : in template argument for type « unsigned int » 
             const auto factory = std::get<std::integral_constant<std::size_t, id>{}>(_factories).second;
                                                                                 ^

我正在使用这些命令来编译:

(clan)g++ -std=c++14 -O2 -Wall -pedantic -Wextra main.cpp

使用g++ v6.3.1clang++ v3.9.1

看起来对应于我的问题的唯一链接是GCC4.9的错误报告(已解决(:https://gcc.gnu.org/bugzilla/show_bug.cgi.iid=59937.p>这里提供一个最小的工作示例。

从我对gcc错误消息的理解,我不应该有任何错误:id不用用于初始化。

此代码是否会产生错误?

如果要引起错误,我该怎么办才能解决错误?

谢谢您的回答。

完整的代码:

#include <iostream>
#include <vector>
#include <memory>
#include <string>
#include <functional>
#include <utility>
#include <type_traits>
#include <tuple>
#include <experimental/any>
template <class F, class... Ts>
constexpr void for_each_in_tuple(const std::tuple<Ts...> &tuple, F f) {
    for_each_in_tuple(tuple, f, std::make_index_sequence<sizeof...(Ts)>());
}

template <class F, class... Ts, std::size_t... Is>
constexpr void for_each_in_tuple(const std::tuple<Ts...> &tuple, F f, std::index_sequence<Is...>) {
    using expander = int[];
    (void) expander{0, ((void)f(Is, std::get<Is>(tuple)), 0)...};
}
template <typename... Connectors>
class ConnectionPool {
    public:
        auto getConnection(const std::string &name) {
            constexpr const std::size_t id{findFactoryId(_factories, name)};
            const auto factory = std::get<std::integral_constant<std::size_t, id>{}>(_factories).second;
            return factory();
        }
    private:
        struct foo {
            constexpr foo(std::size_t &i, const std::string &name) : i(i), name(name) {}
            template <class T>
            constexpr void operator()(const std::size_t is, const T pair) {
                i = name == pair.first ? is : i;
            }
            std::size_t &i;
            const std::string &name;
        };
        template <class Tuple>
        static constexpr std::size_t findFactoryId(Tuple &tup, const std::string &name) {
            std::size_t i = 0;
            for_each_in_tuple(tup, foo(i, name));
            return i;
        }
        std::tuple<std::pair<std::string, std::function<Connectors()>>...> _factories;
};

int main()
{
    return 0;
}

编辑

更改链接到最小工作示例:缺少一个函数。

编辑2

在帖子中添加最小工作示例

问题在此行上:

constexpr const std::size_t id{findFactoryId(_factories, name)};

constexpr变量的初始化器必须是恒定表达式。在恒定表达式中,您无法使用this指针。您是通过参考_factories(即数据成员(隐式使用this指针。

n4296 [expr.const]&para; 2

a 条件表达 e corce constant表达式,除非评估e ...将评估以下表达式之一:

  • this,除了constexpr功能或constexpr构造函数以外,该构造器正在e的一部分;
  • ...

令人惊讶的是,如果我们只使用明确的this

,这两个编译器都很高兴
constexpr const std::size_t id{findFactoryId(this->_factories, name)};

,但我不认为这是一致的。这是便携式解决方法:

const auto _this = this;
constexpr const std::size_t id{findFactoryId(_this->_factories, name)};