There is some function that takes as an argument a vector of any type through a template.

template <typename T> bool my_function( const std::vector< T >& vec, bool pairs ) { if( pairs ) return vec[0].first < vec[1].first; else return vec[0] < vec[1]; } 

The function has a second argument indicating whether the function is passed a vector of type std :: pair <>, for example, std :: pair <int, int>. Call example:

 std::vector< std::pair< int, int > > v( std::pair< int, int >(0, 0), std::pair< int, int >(1, 1) ); bool res = my_function( v, true ); 

This code compiles normally, but if now somewhere in another place to call this function with a vector of just integer values ​​(and not pairs) and the false flag, which logically should work correctly, an error will occur at the compilation stage:

 std::vector< int > v2( 0, 1 ); bool res2 = my_function( v2, false ); ////// error: request for member 'first' in 'vec.std::vector<_Tp, _Alloc>::operator[]<int, std::allocator<int> >(0)', which is of non-class type 'const value_type {aka const int}' 

An attempt to correct the situation via dynamic_cast was not successful:

 template <typename T> bool my_function( const std::vector< T >& vec, bool pairs ) { if( pairs ) { const std::pair< int, int >* v_0 = dynamic_cast< const std::pair< int, int >* >(&vec[0]); const std::pair< int, int >* v_1 = dynamic_cast< const std::pair< int, int >* >(&vec[1]); return v_0->first < v_1->first; } else return vec[0] < vec[1]; } ///// error: cannot dynamic_cast '& vec.std::vector<_Tp, _Alloc>::operator[]<int, std::allocator<int> >(0)' (of type 'const value_type* {aka const int*}') to type 'const struct std::pair<int, int>*' (source is not a pointer to class) 

How to calm the compiler? Maybe there is a way to more elegantly generalize types, without using the second parameter pairs? Variants with typeid didn't work either.

  • This is called constexpr if , will be in the next version of the language. - Abyx

1 answer 1

Why don't you take advantage of the specialization:

 template<typename T> bool my_function( const std::vector<T>& vec) { return vec[0] < vec[1]; } template<typename T> bool my_function( const std::vector<pair<T,T>>& vec) { return vec[0].first < vec[1].first; } 

It is possible and simple overload, by the way ...

  • yes, but I wonder if there is a way to implement this type generalization in just one function? - user232238
  • How it works? After all, the vector of pairs is also suitable for the first pattern. - pank
  • @ layer19, better not do that. I already asked a similar question: ru.stackoverflow.com/questions/579570/… - pank
  • @pank Read about specialization - in this case, the second template more accurately corresponds to the transferred type. As for your advice not to do so - it would be interesting to understand 1. why and 2. what do you think should be done? ... - Harry
  • 2
    Well, what dynamic_cast to the templates? Where is your inheritance, virtual functions? reinterpret_cast - well, not in this case! Understand that the idea itself, apart from the type of passing a variable into the template function, indicates that this type is nonsense! ... - Harry