C++ 为什么std::variant使用开始和结束迭代器编译?

C++ 为什么std::variant使用开始和结束迭代器编译?,c++,std-variant,C++,Std Variant,编译器似乎应该能够捕捉到std::variant没有迭代器方法这一事实,但我的代码编译起来似乎没有问题(即使我随机为变量编写方法或成员变量),但它在运行时崩溃(这是理所当然的)。有人能解释一下为什么要编译这段代码吗 注意:这并没有阻止进程,因为现在我使用的是std::visit,但是如果知道为什么要编译它,那就太好了 我尝试过使用不同的变体模式,它们都可以编译。参见代码示例。您可以将其弹出到cppreferences或godbolt中,它应该使用C++17或更高的标志进行编译 #include

编译器似乎应该能够捕捉到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 )  )
      {

      }
}
#包括
#包括
#包括
#包括
#包括
#包括
模板
//使用var_maps=std::variant;
//使用var_maps=std::variant;
使用var_maps=std::variant;
模板
空平面(常量变量映射和vmap)
{
//对于(auto-bIter=vmap.bexxxgin(),eIter=vmap.end();bIter!=eIter;
对于(auto-bIter=vmap.begin(),eIter=vmap.end();bIter!=eIter;
bIter=vmap.上限(bIter->first))
{
}
}
我最初使用的是maps,但它可以有效地编译任何东西。此外,我可以将begin()随机替换为任何其他单词,它仍然可以编译。我知道正确的方法是访问。我不可避免地尝试使用一个函数来处理map和multimap,并将其转换为另一个数据结构

谢谢!

它“编译”,因为函数是一个模板。在这里,除了基本语法检查之外,没有生成任何代码。解析模板时,无法完成任何检查

这是因为编译器不知道
var\u映射是否包含
begin()


当您实例化
var\u映射时,您将收到错误,即对具体类型
K
V

使用
var\u映射
,因为
begin()
end()
是依赖名称-它们依赖于函数模板参数,因此它们的查找被推迟到
平面
模板实例化。但它从未被实例化

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

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

我明白了,所以所有模板化的方法都被推迟到实例化(不管类型如何)。我不明白的是,std::variant永远不会有一个开始和结束迭代器,对吗?这实际上什么时候起作用?我想我不能在K和V中放置任何类型,使variant有一个开始和结束方法?