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

时间:2019-08-10 17:47:27

标签: c++ std-variant

似乎编译器应该能够捕捉到std :: variant没有迭代器方法的事实,但是看来我的代码编译没有问题(即使我随机地为该方法组合了方法或成员变量)变体),但它会在运行时崩溃(理应如此)。有人可以阐明为什么要编译此代码吗?

注意:这不会阻止进度,因为现在我正在使用std :: visit,但是很高兴知道为什么要编译。

我尝试使用不同的变体模式,它们都可以编译。请参见代码示例。您可以将其弹出到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 )  )
      {

      }
}

我最初的案例是关于地图的,但是它可以有效地编译任何东西。另外,我可以将begin()随机替换为其他任何单词,并且仍然可以编译。我知道正确的方法是拜访。我不可避免地试图拥有一个同时处理地图和多地图的功能,并将其转换为另一种数据结构。

谢谢!

2 个答案:

答案 0 :(得分:2)

您的代码会编译,因为yay -S dotnet-sdkbegin()是从属名称-它们取决于函数模板参数,因此它们的查找将推迟到end()模板实例化之前。但是它永远不会被实例化!

如果添加以下内容,则代码将不再编译:

flat

答案 1 :(得分:1)

“编译”是因为该功能是模板。解析基本模板后,此处不会生成任何代码,而且无法进行基本语法检查。

这是因为编译器不知道updated_at是否包含var_maps<K,V>。可能会有专长。

实例化begin()时,即将var_maps与具体类型var_mapsK结合使用时,会收到错误消息。