Detecting if a type can be obtained from C ++

I have the following template class and a (global) variable of its type:

template <typename ClassT> struct ClassTester : public ClassT { typedef ClassT type; }; ClassTester<int> *aaa; // No error here 

I expect a compilation error because int cannot be obtained, but this compiles in Visual C ++ 2010.

If I delete the pointer, I get the expected compilation error (int cannot be obtained):

 ClassTester<int> bbb; // Error here 

I wanted to use this class to test SFINAE whether this type is a class that can be obtained from:

 template <typename T> struct CanBeDerivedFrom { template <typename C> static int test(ClassTester<T> *) { } template <typename> static char test(...) { } static const bool value = (sizeof(test<T>(0)) == sizeof(int)); }; 

This, however, always returns true even for primitive types such as int due to the above reason. Is this the expected / acceptable behavior of C ++?

+6
source share
6 answers

I think it is not possible to fully get a class that is output via SFINAE (which also includes final class cases in C ++ 11). The best you can do is get SFINAE for your search if the class type and rely on it.

 template<typename T> struct void_ { typedef void type; }; template<typename T, typename = void> struct CanBeDerivedFrom { static const bool value = false; }; template<typename T> struct CanBeDerivedFrom<T, typename void_<int T::*>::type> { static const bool value = true; }; 

This metaprogram will find if the given type is class/union or not. demonstration .

+1
source

Do not reinvent the wheel. Use boost :: is_class acceleration reference

These guys know better than you.

+4
source

Unfortunately, I think this is actually impossible.

Many problems can prevent derivation (or at least a useful conclusion) by adding final to the standard being one.

For example, see this thread on the Clang mailing list, where Howard Hinnant needs a compiler to check if the class is marked final or not.

+2
source

I was going to offer as a visitor. I do not believe that a pointer declaration will instantiate a template, so it can compile. Try accessing the element using the template using a pointer that forces the compiler to instantiate the template. Otherwise, I'm not sure, but I know that you cannot inherit an integer type.

So, an answer that I suppose you wonโ€™t need, since the code probably wonโ€™t compile if you try to instantiate a template class that inherits an integer type. Maybe I'm wrong, but I believe that the only reason it compiles is because creating a pointer type does not create an instance of the template.

+1
source

You can use RTTI (runtime type information) to find out which type the class belongs to, and if the class has a base type, you can say that the class cannot be obtained.

Example: if (typeid (T) == typeid (int) || typeid (T) == typeid (float)) {cout <"Class cannot be obtained from"; }

You can add more types if you wish to the IF condition

0
source
 #include <typeinfo> 

 main() { int i; int * pi; cout << int is: << typeid(int).name() << endl; cout << i is: << typeid(i).name() << endl; cout << pi is: << typeid(pi).name() << endl; cout << *pi is: << typeid(*pi).name() << endl << endl; 

} Code>

he prints:

 int
 int
 int *
 int

as was expected.

someone should be independent of another library ... so upgrading a library is not a good answer.

0
source

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


All Articles