var在自己的初始化器中使用 [英] var used in its own initializer
问题描述
以下代码:
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; (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 ++给出这个错误:
在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:id的值在常量中不可用表达式
const auto factory = std :: get< std :: integral_constant< std :: size_t,id> {}>(_ factories).second;
^〜
src / core / include / connectionpool.h:27:41:note:在其自己的初始化程序中使用的id
constexpr const std :: size_t id {findFactoryId(_factories,名称)};
^〜
src / core / include / connectionpool.h:28:81:erreur:常量表达式中不能使用id的值
const auto factory = std :: get< std :: integral_constant< std :: size_t,id> {}>(_ factories).second;
^
src / core / include / connectionpool.h:27:41:note:在其自己的初始化程序中使用的id
constexpr const std :: size_t id {findFactoryId(_factories,name )};
^〜
src / core / include / connectionpool.h:28:81:注意:在类型为«unsigned int»的模板参数中,
const auto factory = std :: get
我正在使用这些命令进行编译:
(clan)g ++ -std = c ++ 14 -O2 -Wall -pedantic -Wextra main.cpp
与 g ++ v6.3.1
和 clang ++ v3.9.1
$ b
看起来与我的问题相对应的唯一链接是gcc4.9的缺陷报告(已解决): https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59937 。
一个最简单的工作示例可在此处。
从我所了解的 gcc
错误信息,我不应该有任何错误: id
不用于自我初始化。
这段代码是否会产生错误?
如果它应该提出一个错误,我能做些什么来解决这个错误?
谢谢你的回答。
完整的代码:
#include< iostream>
#include< vector>
#include< memory>
#include< string>
#include< functional>
#include< utility>
#include< type_traits>
#include< tuple>
#include< experimental / any>
模板< 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) >());
}
模板< 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)...};
}
模板< typename ...连接器>
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();
$ b private:
struct foo {
constexpr foo(std :: size_t& i,const std :: string& name):i(i ),名称(名称){}
模板< class T>
constexpr void operator()(const std :: size_t is,const T pair){
i = name == pair.first?是:我;
}
std :: size_t& i;
const std :: string& name;
};
模板< 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));
返回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]¶ 2
条件表达式 e ...会评估e 是一个核心常量表达式以下表达式之一:
this
,除了constexpr
函数或c> constexpr 构造函数,它被评估为 e
的一部分。
令人惊讶的是,两种编译器都是如果我们简单地使用明确的这个
:constexpr const std: :size_t id {findFactoryId(this-> _factories,name)};
但我不相信这是一致的。这是一个便携式的解决方法:
const auto _this = this;
constexpr const std :: size_t id {findFactoryId(_this-> _factories,name)};
The following code :
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; }
compile with clang++, but with g++ gives this error:
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; ^
I'm using those command to compile:
(clan)g++ -std=c++14 -O2 -Wall -pedantic -Wextra main.cpp
with
g++ v6.3.1
andclang++ v3.9.1
The only link that look like to correspond to my issue is a bug report for gcc4.9 (which is solved) : https://gcc.gnu.org/bugzilla/show_bug.cgi?id=59937.
A minimal working example is available here.
From what I've understood of
gcc
error message, I should not have any error:id
isn't used to initialise itself.Should this code yield an error or not ?
If it should raise an error, what could I do to solve the error ?
Thank you for your answers.
The complete code:
#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; }
EDIT
Change link to minimal working example: a function was missing.
EDIT 2
Add minimal working example in the post
解决方案The problem is on this line:
constexpr const std::size_t id{findFactoryId(_factories, name)};
The initializer of a
constexpr
variable must be a constant expression. In a constant expression you can not use thethis
pointer. You are implicitly using thethis
pointer by referring to_factories
, which is a data member.N4296 [expr.const] ¶2
A conditional-expression
e
is a core constant expression unless the evaluation ofe
... would evaluate one of the following expressions:
this
, except in aconstexpr
function or aconstexpr
constructor that is being evaluated as part ofe
;- ...
Surprisingly, both compilers are happy if we simply use an explicit
this
:constexpr const std::size_t id{findFactoryId(this->_factories, name)};
But I do not believe that is conformant. Here is a portable workaround:
const auto _this = this; constexpr const std::size_t id{findFactoryId(_this->_factories, name)};
这篇关于var在自己的初始化器中使用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!