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
?
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.
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 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#.
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.
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
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With