Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to detect if a method is virtual?

I tried to make a traits to find if a method is virtual: (https://ideone.com/9pfaCZ)

// Several structs which should fail depending if T::f is virtual or not. template <typename T> struct Dvf : T { void f() final; }; template <typename T> struct Dvo : T { void f() override; }; template <typename T> struct Dnv : T { void f() = delete; };  template <typename U> class has_virtual_f { private:     template <std::size_t N> struct helper {};     template <typename T>     static std::uint8_t check(helper<sizeof(Dvf<T>)>*);     template<typename T> static std::uint16_t check(...); public:     static     constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); }; 

Test cases:

struct V  { virtual void f(); }; struct NV {         void f(); }; struct E  {                   }; struct F  { virtual void f() final; }; // Bonus (unspecified expected output)  static_assert( has_virtual_f< V>::value, ""); static_assert(!has_virtual_f<NV>::value, ""); static_assert(!has_virtual_f< E>::value, ""); 

But I got error: 'void Dvf<T>::f() [with T = NV]' marked final, but is not virtual.
If I don't use sizeof and directly Dvf<T>* in check, I don't have compilation error, but check is not discarded for "bad" type in SFINAE :( .

What is the proper way to detect if a method is virtual ?

like image 788
Jarod42 Avatar asked Apr 07 '14 11:04

Jarod42


People also ask

Do you know what a virtual function is?

A virtual function is a member function in the base class that we expect to redefine in derived classes. Basically, a virtual function is used in the base class in order to ensure that the function is overridden. This especially applies to cases where a pointer of base class points to an object of a derived class.

Are methods in Java Virtual?

In Java, all non-static methods are by default "virtual functions." Only methods marked with the keyword final, which cannot be overridden, along with private methods, which are not inherited, are non-virtual.

What are virtual methods?

What Does Virtual Method Mean? A virtual method is a declared class method that allows overriding by a method with the same derived class signature. Virtual methods are tools used to implement the polymorphism feature of an object-oriented language, such as C#.

Can you call a virtual method?

Virtual functions allow a program to call methods that don't necessarily even exist at the moment the code is compiled. In C++, virtual methods are declared by prepending the virtual keyword to the function's declaration in the base class.


2 Answers

The code isn't perfect but it basically passes the tests (at least in all clangs available on wandbox and gcc since 7.):

#include <type_traits>  template <class T> using void_t = void;  template <class T, T v1, T v2, class = std::integral_constant<bool, true>> struct can_be_compaired: std::false_type { };  template <class T, T v1, T v2> struct can_be_compaired<T, v1, v2, std::integral_constant<bool, v1 == v2>>: std::true_type { };  template <class T, class = void> struct has_virtual_f: std::false_type { };  template <class T> struct has_virtual_f<T, void_t<decltype(&T::f)>>{     constexpr static auto value = !can_be_compaired<decltype(&T::f), &T::f, &T::f>::value; };  struct V  { virtual void f() { }      }; struct NV {         void f() { }      }; struct E  {                           }; struct F  { virtual void f() final{ } }; // Bonus (unspecified expected output)  int main() {    static_assert( has_virtual_f< V>::value, "");    static_assert(!has_virtual_f<NV>::value, "");    static_assert(!has_virtual_f< E>::value, "");    static_assert( has_virtual_f< F>::value, ""); } 

[live demo]


The relevant standard parts that theoretically let the trait fly: [expr.eq]/4.3, [expr.const]/4.23

like image 77
W.F. Avatar answered Sep 30 '22 08:09

W.F.


There is probably no way to determine if a specific method is virtual. I say this because the Boost project researched traits for years and never produced such a traits test.

However, in C++11, or using the Boost library, you can use the is_polymorphic<> template to test a type to see if the type has virtual functions. See std::is_polymorphic<> or boost::is_polymorphic<> for reference.

like image 22
llewelly Avatar answered Sep 30 '22 09:09

llewelly