以下代码:
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.1
和clang++ v3.9.1
与我的问题相对应的唯一链接是gcc4.9的错误报告(已解决):https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59937。
可以使用最小的工作示例here。
根据我对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
在帖子中添加最小的工作示例
答案 0 :(得分:4)
问题在于这一行:
constexpr const std::size_t id{findFactoryId(_factories, name)};
constexpr
变量的初始值设定项必须是常量表达式。在常量表达式中,您不能使用this
指针。您通过引用this
隐式使用_factories
指针,e
是数据成员。
N4296 [expr.const]¶2
条件表达式
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)};
但我不相信这是符合的。这是一个便携式解决方法:
for i in ...