c ++为什么这个static_assert有效:

时间:2018-03-04 20:47:28

标签: c++ c++17 constexpr variant static-assert

我对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 
}

2 个答案:

答案 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);

因为var1constexprstd::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