0

I need to know if I am sending a template class the right type of containers by applying downcast.

// C++ program to demonstrate input iterator
#include <iostream>
#include <vector>
#include <iterator>
using namespace std;
int main()
{
    vector<int> v1 = { 1, 2, 3, 4, 5 };

    // Declaring an iterator
    vector<int>::iterator i1;
    bidirectional_iterator & bi = dynamic_cast<i1&>(i1);
    if(bi != nullptr)
      cout << "Succesfull" << endl;
    for (i1 = v1.begin(); i1 != v1.end(); ++i1) {
        // Accessing elements using iterator
        cout << (*i1) << " ";
    }
    return 0;
}

I get the error:

prog.cpp: In function ‘int main()’:
prog.cpp:12:2: error: ‘bidirectional_iterator’ was not declared in this scope
  bidirectional_iterator & bi = dynamic_cast<i1&>(i1);
  ^
prog.cpp:12:27: error: ‘bi’ was not declared in this scope
  bidirectional_iterator & bi = dynamic_cast<i1&>(i1);
                           ^
prog.cpp:12:45: error: ‘i1’ does not name a type
  bidirectional_iterator & bi = dynamic_cast<i1&>(i1);
                                             ^
prog.cpp:12:47: error: expected ‘>’ before ‘&’ token
  bidirectional_iterator & bi = dynamic_cast<i1&>(i1);
                                               ^
prog.cpp:12:47: error: expected ‘(’ before ‘&’ token
prog.cpp:12:48: error: expected primary-expression before ‘>’ token
  bidirectional_iterator & bi = dynamic_cast<i1&>(i1);
                                                ^
prog.cpp:12:53: error: expected ‘)’ before ‘;’ token
  bidirectional_iterator & bi = dynamic_cast<i1&>(i1);

Is there anyway I can check the type of iterator in a container so I can control whether it will be passed in a templated class?

Kamil Kaya
  • 47
  • 5
  • 1
    Looks like you might need: https://en.cppreference.com/w/cpp/iterator/iterator_traits – NathanOliver Jan 11 '21 at 19:49
  • 2
    looks like you are casting using the variable as type `dynamic_cast` – AndersK Jan 11 '21 at 19:50
  • 1
    You should not compare iterators to `nullptr`. It is not meaningful, and usually it won't even compile. Additionally, `dynamic_cast` will throw `std::bad_cast` on failure. You should only use a `nullptr` comparison to check if `dynamic_cast` succeeds if you are casting a pointer. `dynamic_cast` returns `nullptr` on failure instead of throwing. – François Andrieux Jan 11 '21 at 19:53
  • you can just use the iterator as if it is a bidirectional one, and if it isnt the template instantiation will fail. If it walks like a duck and quacks like a duck, it is a duck – 463035818_is_not_an_ai Jan 11 '21 at 19:53
  • @NathanOliver Yes. This is definitely what I needed. Thanks for advice. – Kamil Kaya Jan 12 '21 at 12:08

2 Answers2

2

Looks like you have completely misunderstood iterators in standard library. First and foremost, if you ever find yourself doing dynamic_cast with any standard library type (a notable exception - he-he, pun - is std::exception, and perhaps a couple of other types I am not thinking of right now) you are doing something wrong. The vast majority of STL types are not polymorphic and should never be used as such.

This is true of iterators as well. You do not need to cast std::vector::iterator to biderectional_iterator, instead you just use it where such iterator is required. There are iterator_traits, which, when used with vector iterators will indicate that vector's iterators are bidrectional through iterator_category. See more information on iterator_traits

The beauty of traits is that all this logic is done at compile time, so if you are trying to use in iterator in a scenario it is no capable to handle, you end up with compile error, and can fix the program immediately.

SergeyA
  • 61,605
  • 5
  • 78
  • 137
1

dynamic_cast performs runtime inspection of an instantiated object.

Template resolution works (primarily) on types (not objects) and happens at compile time. An example of compile time inspection of a type would be std::is_base_of<Base,Type>

vector<int>::iterator i1;

using iterator_type = std::iterator_traits<decltype(i1)>::iterator_category;
if( std::is_base_of_v<std::bidirectional_iterator_tag,iterator_type> )
// Can be "if constexpr" above, since this is known at compile time
{
  cout << "Succesfull" << endl;
Drew Dormann
  • 59,987
  • 13
  • 123
  • 180
  • I think I got this. It was very unfamiliar concept for me. But I get the point. I will try this method. Thank You. – Kamil Kaya Jan 12 '21 at 12:05