#include <cstdint>

// Seveval 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);
};

// Sample struct.
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, "");
//static_assert(/* ! */ has_virtual_f< F>::value, ""); (unspecified expected output)

int main() {
	return 0;
}
