Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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!

like image 838
mriera Avatar asked Mar 20 '26 02:03

mriera


2 Answers

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>;
}
like image 72
Igor R. Avatar answered Mar 22 '26 16:03

Igor R.


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, i.e. use var_maps with concrete types K and V.

like image 40
Andreas H. Avatar answered Mar 22 '26 14:03

Andreas H.



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!