我对constexpr
有以下问题,我知道有人不能声明std::shared_ptr<T>
为const
,但为什么第一个static_assert()
有效?< / p>
此外,第二个static_assert()
如何运作?我希望有一个std::variants
数组,它们是consts,并希望进行编译时类型检查以强制执行该类型;但是,似乎如果std::shared_ptr
是变体类型之一,则无法将其声明为constexpr
;但如果我将容器声明为std::tuple
,即使没有constexpr
注释,(I)似乎也可以工作;
typedef std::shared_ptr<int> intp;
const auto defaults = std::make_tuple(std::make_pair(1, true),
std::make_pair(2, 3),
std::make_pair(3, intp(nullptr)));
typedef std::variant<int, bool> MyVar;
constexpr MyVar var1 = 3;
// constexpr intp x = nullptr; (I)
//typedef std::variant<int, bool, intp> MyVar2; This doesn't work
//constexpr MyVar2 var2 = 3;
int main()
{
// Q1): Why the following works, but (I) does not.
static_assert(std::is_same<decltype(std::get<2>(defaults).second), intp>::value);
// Q2): Why this works: is there a better way to say something like
// static_assert(actual_type(var1) == int);
static_assert(std::get<int>(var1) == 3);
//static_assert(x == nullptr); This does not work
}
答案 0 :(得分:3)
我有点理解,不能将shared_ptr声明为const,但为什么第一个static_assert有效?
由于
static_assert(std::is_same<decltype(std::get<2>(defaults).second), intp>::value);
不会创建编译时stared_ptr
;仅检查std::get<2>(defaults).second
的类型是否为intp
。
如果值仅在运行时可用,则此信息在编译时也是已知的。
另外,第二个static_assert是如何工作的?我想要一个std :: variants数组,它们是consts,并希望进行编译时类型检查以强制执行该类型;但是,似乎如果shared_ptr是变体类型之一,则它不能被声明为constexpr;但如果我将容器声明为std :: tuple,即使没有constexpr注释,(I)似乎也可以工作;
不确定你的意思。
如果“second static_assert work”是指你的意思
static_assert(std::get<int>(var1) == 3);
因为var1
是constexpr
而std::get()
(std::variant
)是constexpr
;所以std::get<int>(var1)
它是static_assert()
中可以使用的值,编译时间
与
答案 1 :(得分:0)
// Q1):为什么以下有效,但(I)没有。
[2018-03-05T21:20:51,014][WARN ][logstash.outputs.elasticsearch] Restored connection to ES instance {:url=>"http://oida-elk:9200/"} [2018-03-05T21:20:51,078][INFO ][logstash.outputs.elasticsearch] Using mapping template from {:path=>nil} [2018-03-05T21:20:51,085][INFO ][logstash.outputs.elasticsearch] Attempting to install template {:manage_template=>{"template"=>"logstash-*", "version"=>60001, "settings"=>{"index.refresh_interval"=>"5s"}, "mappings"=>{"_default_"=>{"dynamic_templates"=>[{"message_field"=>{"path_match"=>"message", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false}}}, {"string_fields"=>{"match"=>"*", "match_mapping_type"=>"string", "mapping"=>{"type"=>"text", "norms"=>false, "fields"=>{"keyword"=>{"type"=>"keyword", "ignore_above"=>256}}}}}], "properties"=>{"@timestamp"=>{"type"=>"date"}, "@version"=>{"type"=>"keyword"}, "geoip"=>{"dynamic"=>true, "properties"=>{"ip"=>{"type"=>"ip"}, "location"=>{"type"=>"geo_point"}, "latitude"=>{"type"=>"half_float"}, "longitude"=>{"type"=>"half_float"}}}}}}}} [2018-03-05T21:20:51,101][INFO ][logstash.outputs.elasticsearch] New Elasticsearch output {:class=>"LogStash::Outputs::ElasticSearch", :hosts=>["//oida-elk:9200"]} [2018-03-05T21:20:51,297][INFO ][logstash.pipeline ] Starting pipeline {:pipeline_id=>"main", "pipeline.workers"=>1, "pipeline.batch.size"=>125, "pipeline.batch.delay"=>5, "pipeline.max_inflight"=>125, :thread=>"#<Thread:0x2ea3b180@/home/data/logstash-6.0.0/logstash-core/lib/logstash/pipeline.rb:290 run>"} [2018-03-05T21:20:51,746][INFO ][logstash.pipeline ] Pipeline started {"pipeline.id"=>"main"} [2018-03-05T21:20:51,800][INFO ][logstash.agent ] Pipelines running {:count=>1, :pipelines=>["main"]}
这就是魔术:在C ++中,一些表达式被认为是 未评估的 。 static_assert(std::is_same<decltype(std::get<2>(defaults).second), intp>::value);
是其中之一(请参阅[dcl.type.simple])
decltype(...)
未被评估是什么意思?
在这种背景下,共同的目的 写表达式只是为了指代它的类型。
认为它更像是一种幻想decltype(...)
。在此上下文中实际上无法创建任何内容。你可以用它做一些有趣的事情,比如使用不完整的类型。
原因
typedef
现在变得不明显了:这个表达式被评估,因为我们知道我们无法创建typedef std::shared_ptr<int> intp;
constexpr intp x = nullptr;
,所以编译失败。
// Q2):为什么这样有效:是否有更好的方式来表达像
constexpr shared_ptr
?
// static_assert(actual_type(var1) == int);
这是有效的,因为std::variant
有一个static_assert(std::get<int>(var1) == 3);
构造函数,并且您使用编译时整数值constexpr
构造它,构造了3
的{{1}}字段。变体。
接下来,int
上的std::get
也标记为variant
,由于变体的构造为constexpr
,我们可以获取编译时的值为constexpr
。