简体   繁体   English

为什么std :: variant用begin和end迭代器编译?

[英]Why does a std::variant compile with begin and end iterators?

It seems that the compiler should be able to catch the fact that std::variant doesn't have iterator methods, but it seems that my code compiles with no problem (even if I randomly make up methods or member variables for the variant), but it crashes at runtime (rightfully so). 似乎编译器应该能够捕获std :: variant没有迭代器方法的事实,但似乎我的代码编译没有问题(即使我随机组成变量的方法或成员变量),但它在运行时崩溃(理所当然)。 Can someone shed some light on why this code compiles? 有人可以解释为什么这个代码编译?

Note: this isn't blocking progress because now I'm using std::visit, but it would be nice to know why this is compiling. 注意:这不会阻止进度,因为现在我正在使用std :: visit,但是知道为什么要编译它会很好。

I have tried using different variant patterns and they all compile. 我尝试使用不同的变体模式,它们都编译。 See code examples. 请参阅代码示例。 You can pop this in to cppreferences, or godbolt and it should compile with C++17 flags or greater 你可以将它弹出到cppreferences或godbolt,它应该用C ++ 17标志或更高的标志进行编译

#include <variant>
#include <string>
#include <cassert>
#include <iostream>
#include <list>
#include <map>

template<typename K, typename V>
//using var_maps = std::variant<std::map<K,V>, std::multimap<K,V> >;
//using var_maps = std::variant<std::list<int>, std::list<float> >;
using var_maps = std::variant<int, float>;

template <typename K, typename V>
void flat( const var_maps<K,V>& vmap)
{
    //for(auto bIter = vmap.bexxxgin(), eIter = vmap.end(); bIter != eIter;
    for(auto bIter = vmap.begin(), eIter = vmap.end(); bIter != eIter;
      bIter = vmap.upper_bound( bIter->first )  )
      {

      }
}

My initial case was with maps, but it effectively compiles with anything. 我最初的情况是使用地图,但它有效地编译了任何东西。 Additionally I can randomly replace begin() to any other word and it still compiles. 另外,我可以随意将begin()替换为任何其他单词,它仍然可以编译。 I know the right way to do this is with visits. 我知道正确的方法是访问。 I am inevitably trying to have one function that handles both map and multimap and transform it to another data structure. 我不可避免地尝试使用一个处理map和multimap的函数,并将其转换为另一个数据结构。

Thank you! 谢谢!

Your code compiles, because begin() and end() are dependent names - they depend on the function template arguments, so their lookup is postponed until the flat template instantiation. 您的代码编译,因为begin()end()是依赖名称 - 它们依赖于函数模板参数,因此它们的查找被推迟到flat模板实例化。 But it is never instantiated! 但它永远不会被实例化!

If you add the following, your code won't compile anymore: 如果添加以下内容,则代码将不再编译:

int main () {
     &flat<int, int>;
}

It "compiles" because the function is a template. 它“编译”因为函数是一个模板。 No code is generated here and beyond basic syntax checking no complete checking can be done when the template is parsed. 这里没有生成代码,除了基本语法检查之外,在解析模板时不能进行完整的检查。

This is because the compiler does not know whether the var_maps<K,V> contains begin() or not. 这是因为编译器不知道var_maps<K,V>包含begin() There could be specializations. 可能有专业化。

You will receive the error when you instantiate var_maps , ie use var_maps with concrete types K and V . 实例化var_maps时会收到错误,即使用具有类型KV var_maps

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM