简体   繁体   中英

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). 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.

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

#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. 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.

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. 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. There could be specializations.

You will receive the error when you instantiate var_maps , ie use var_maps with concrete types K and V .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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