Converting runtime convertibility in C ++

In C ++, type conversions are implicitly performed. For example, an object of type int can be assigned const int (as is done in the first lines of the main function in the code below).

Now I want to check the convertibility at runtime that I have a structure in which I can add types, and later I want to check for a given type if one of the types stored in the structure is converted to the given type.

Here is what I came up with so far:

 #include <iostream> #include <vector> struct bar { virtual void dummy() {} }; template<typename T> struct foo : public bar { virtual void dummy() {} }; int main() { int i1 = 1; const int i2 = i1; std::vector<bar*> bars; bar* t1 = new foo<int>; bars.push_back(t1); bar* t2 = new foo<int const>; bars.push_back(t2); foo<int const>* t3 = dynamic_cast<foo<int const>*>(bars[0]); std::cout << t3 << std::endl; foo<int const>* t4 = dynamic_cast<foo<int const>*>(bars[1]); std::cout << t4 << std::endl; delete t1; delete t2; return 0; } 

To store types in a structure, I created a template structure foo , which is derived from bar . Then I can store different types of int and int const (more precisely, pointing to objects of type foo<int> and foo<int const> ) in the vector bar* s. Then for a given type (here int const ) I check every element in this vector if it can be dynamically added to foo with this type.

When this code is run, t3 becomes nullptr and t4 non-zero pointer. But I wanted to have a non-zero pointer for t3 as well.

I hope it has become clear what I want to do.

Do you have any ideas on how to achieve such a check on the possibility of conversion at runtime (a solution using 11 C ++ functions would be completely fine)?

+4
source share
2 answers

Unfortunately, since foo<int> and foo<const int> are completely unrelated types, you cannot do this easily.

 bar* t1 = new foo<int>; foo<int const>* t3 = ?????<foo<int const>*>(t1); 

t3 cannot be a pointer in any part of t1 , since t1 does not have and does not contain a foo<int const> for t3 to indicate. The only way to get any good behavior out of this is to make a copy of the data that t1 contains in itself the new foo<int const>* . This disappointing limitation is a side effect of templates that specialize in unrelated types, which is an extremely powerful tool, but leads to this confusion. The general rule is to NOT put const / volatile qualifications or references of any type in the template parameters, unless that is the only reason for the template class (e.g. std::remove_reference ).

However, I just realized that you want foo<int> and foo<const int> be of the same type (ish), and it can be done (sortof)!

 struct base { virtual ~base(){}; //always have virtual destructor with polymorphism virtual void dummy()=0; //pure virtual, forces override }; template<typename T> struct foo : public bar { virtual void dummy() {} }; template<typename T> struct foo<const T> : public foo<T> {}; template<typename T> struct foo<volatile T> : public foo<T> {}; template<typename T> struct foo<const volatile T> : public foo<T> {}; base* t1 = new derived<const int>; derived<int>* t3 = dynamic_cast<derived<int>*>(t1); //hooray! //you can go from derived<const int> to derived<int> but not the other way around 
+5
source

Use std::is_convertible<From*, To*>::value

 #include<type_traits> int main(){ using namespace std; cout << std::is_convertible<int const, int>::value << endl; // print true cout << std::is_convertible<int const*, int*>::value << endl; // print false cout << std::is_convertible<int const, int>::value << endl; // print true cout << std::is_convertible<std::string, int>::value << endl; // print false cout << std::is_convertible<std::string*, int*>::value << endl; // print false } 

Note that you need to use a pointer type to get excluded behavior with respect to const ness, for example.

(I think in C ++ 98 you can do the same with boost::is_convertible .)

-1
source

Source: https://habr.com/ru/post/1488762/


All Articles