How to detect if a method is virtual? - c++

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 ?

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.

Related

C++ conditional template member function

I am trying to understand how to use std::enable_if to choose between 2 functions implementation. In this case, if the type TupleOfCallback doesn't contains all the type, it will not compile because std::get<...> will throw an error.
For exemple:
Executor<Entity1*, Entity2*> task([](Entity1 *e){}, [](Entity2 *2){});
This will not compile because Entity3* is not part of the tuple.
It seem that we can choose between two functions with the same prototype,
void Exec(Entity3 *entity)
{
//enabled when Entity3* is **not** in the tuple
}
OR
void Exec(Entity3 *entity)
{
//enabled when Entity3 is in the tuple
std::get<std::function<void(Entity3*)>>(m_Callbacks)(entity);
}
But i dont understand how to achieve this goal.
C++ template mechanism is still hard for me, any help is welcome.
template<typename ...T>
class Executor
{
typedef std::tuple<std::function<void(T)>...> TupleOfCallback;
public:
Executor(const std::function<void(T)> &...func)
{
}
void Exec(Entity1 *entity)
{
std::get<std::function<void(Entity1*)>>(m_Callbacks)(entity);
}
void Exec(Entity2 *entity)
{
std::get<std::function<void(Entity2*)>>(m_Callbacks)(entity);
}
void Exec(Entity3 *entity)
{
std::get<std::function<void(Entity3*)>>(m_Callbacks)(entity);
}
public:
TupleOfCallback m_Callbacks;
};
Building on this one Check if parameter pack contains a type. You can use two traits to select which method to call:
#include <iostream>
#include <type_traits>
struct Entity1 {};
struct Entity2 {};
struct Entity3 {};
template<typename What, typename ... Args>
struct is_present {
static constexpr bool value {(std::is_same_v<What, Args> || ...)};
};
template<typename T>
struct is_entity : is_present<T,Entity1,Entity2,Entity3> {};
template <typename T, typename ...Args>
struct is_present_entity {
static constexpr bool value = is_present<T,Args...>::value && is_entity<T>::value;
};
template <typename T, typename ...Args>
struct is_not_present_entity {
static constexpr bool value = (!is_present<T,Args...>::value) && is_entity<T>::value;
};
template<typename ...T>
class Executor
{
public:
template <typename U, std::enable_if_t< is_present_entity<U,T...>::value,bool> = true>
void Exec(U* t){
std::cout << "foo\n";
}
template <typename U, std::enable_if_t< is_not_present_entity<U,T...>::value,bool> = true>
void Exec(U* t){
std::cout << "bar\n";
}
};
struct foo {};
int main(void) {
Executor<Entity1,Entity2> ex;
Entity1 e1;
ex.Exec(&e1);
Entity3 e3;
ex.Exec(&e3);
// foo f;
// ex.Exec(&f);
}
output:
foo
bar
Another C++17 option:
template <typename T>
class ExecutorLeaf
{
public:
std::function<void(T)> callback;
void Exec(T entity) { callback(entity); }
};
template <typename... Ts>
class Executor : ExecutorLeaf<Ts>...
{
public:
Executor(const std::function<void(Ts)>&...funcs) : ExecutorLeaf<Ts>{funcs}... {}
using ExecutorLeaf<Ts>::Exec...; // C++17
// Fallback
template <typename T> void Exec(T) {}
};
Demo
If you can guarantee that all types appear only once, then the following should work:
template<typename... Ts>
class Executor {
using TupleOfCallback = std::tuple<std::function<void(Ts)>...>;
public:
Executor(const std::function<void(Ts)>&... func);
template<class E>
std::enable_if_t<(std::is_same_v<Ts, E*> || ...)>
Exec(E* entity) {
std::get<std::function<void(E*)>>(m_Callbacks)(entity);
}
template<class E>
std::enable_if_t<!(std::is_same_v<Ts, E*> || ...)>
Exec(E* entity)
{ }
public:
TupleOfCallback m_Callbacks;
};
The basic idea is to use fold-expression to detect whether E* is included in Ts..., thereby enabling the corresponding function.
Demo.

Detecting a member function in a class which uses CRTP

I am trying to customize a base classes' implementation based on the functions available in a child class using CRTP.
Basic idea of what I want:
// has_inc_function<Child, void> should detect the presence of a member function void Child::inc()
template<class Child, bool = has_inc_function<Child, void>::value>
struct base
{
// ... base implementation stuff
};
template<class Child>
struct base<Child, true>
{
// ... base specialization implementation stuff
};
struct empty : public base<empty>
{};
struct has_inc
{
void inc()
{}
};
struct has_inc_and_crtp : public base<has_inc_and_crtp>
{
void inc()
{}
};
struct has_inc_and_misuse_crtp : public base<has_inc_and_misuse_crtp, true>
{
void inc()
{}
};
struct has_inc_and_misuse_crtp2 : public base<has_inc_and_misuse_crtp, false>
{
void inc()
{}
};
struct no_inc_and_misuse_crtp : public base<no_inc_and_misuse_crtp, true>
{
};
int main()
{
static_assert(has_inc_function<empty, void>::value == false, "");
static_assert(has_inc_function<has_inc, void>::value == true, "");
static_assert(has_inc_function<has_inc_and_crtp, void>::value == true, "");
static_assert(has_inc_function<has_inc_and_misuse_crtp, void>::value == true, "");
static_assert(has_inc_function<has_inc_and_misuse_crtp2, void>::value == true, "");
static_assert(has_inc_function<no_inc_and_misuse_crtp, void>::value == false, "");
}
I've tried a variety of different implementations for has_inc_function<Child, void>, but all of them seem to fail on the case has_inc_and_crtp, and I can't figure out why. I tested with several different compilers via Compiler Explorer, and they all seem to give the same results.
How would I implement has_inc_function so that it works as I would expect in all these test case, or is what I want just not possible?
Implementations I've tried
jrok's solution (Compiler Explorer link):
template <class C, class Ret>
struct has_increment<C, Ret>
{
private:
template <class T>
static constexpr auto check(T*) -> typename std::is_same<
decltype(std::declval<T>().inc()), Ret>::type;
template <typename> static constexpr std::false_type check(...);
typedef decltype(check<C>(nullptr)) type;
public:
static constexpr bool value = type::value;
};
TartanLlama's solution (Compiler Explorer link):
note: that is implementation doesn't match the return type. I've also included sample implementations of stuff in Library fundamentals TS v2 to make this work in C++14
struct nonesuch
{
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
namespace detail {
template <class Default, class AlwaysVoid,
template<class...> class Op, class... Args>
struct detector {
using value_t = std::false_type;
using type = Default;
};
template <class Default, template<class...> class Op, class... Args>
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...> {
using value_t = std::true_type;
using type = Op<Args...>;
};
} // namespace detail
template <template<class...> class Op, class... Args>
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
template <template<class...> class Op, class... Args>
using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
template <class Default, template<class...> class Op, class... Args>
using detected_or = detail::detector<Default, void, Op, Args...>;
template<class...> struct disjunction : std::false_type { };
template<class B1> struct disjunction<B1> : B1 { };
template<class B1, class... Bn>
struct disjunction<B1, Bn...>
: std::conditional_t<bool(B1::value), B1, disjunction<Bn...>> { };
template <typename T>
using has_type_t = typename T::inc;
template <typename T>
using has_non_type_t = decltype(&T::inc);
template <typename T, class RetType>
using has_inc_function =
disjunction<is_detected<has_type_t, T>, is_detected<has_non_type_t, T>>;
Valentin Milea's solution (Compiler Explorer Link):
template <class C, class RetType>
class has_inc_function
{
template <class T>
static std::true_type testSignature(RetType (T::*)());
template <class T>
static decltype(testSignature(&T::inc)) test(std::nullptr_t);
template <class T>
static std::false_type test(...);
public:
using type = decltype(test<C>(nullptr));
static const bool value = type::value;
};
Boost TTI (I couldn't figure out how to get Boost to work with Compiler Explorer):
#include <boost/tti/has_member_function.hpp>
BOOST_TTI_TRAIT_HAS_MEMBER_FUNCTION(has_inc_function, inc);
What you want is in this form plainly not possible. The parent of a class has to be known before the class is complete, and hence before it is known whether the class has such a member function or not.
What you can do is a bit dependent on how different the different instantiations of base are. If they are basically the same interface with different implementation details, you can write another class that has the same interface and a variant member (std::variant is sadly C++17, but you could do the same with dynamic polymorphism) to which all calls are forwarded. Then the decision which to use can be done when instantiating.
You could also try something in this direction:
#include <type_traits>
#include <iostream>
template<class Child>
struct base {
int foo();
};
struct has_inc: base<has_inc> {
void inc();
};
struct has_not_inc: base<has_not_inc> {
};
template<class Child, class = std::void_t<decltype(std::declval<Child>().inc())>>
struct mock {
int foo(base<Child>*) { return 1;}
};
template<class Child>
struct mock<Child> {
int foo(base<Child>*) { return 0;}
};
template<class Child>
int base<Child>::foo() {
return mock<Child,void>().foo(this);
}
int main() {
has_inc h;
has_not_inc n;
std::cout << h.foo() << " " << n.foo() << '\n';
}
Here you only use the complete child of type in the definition, not in the declaration. To the point of the definition, the complete child is available, which it was not during declaration.
There are also other ways (I think, everything is not that easy) and what you can use really depends on your use-case, I would think.
PS: std::void_t is C++17, but it is only template<class...> using void_t = void;.
I've tried a variety of different implementations for has_inc_function<Child, void>, but all of them seem to fail on the case has_inc_and_crtp, and I can't figure out why.
The problem (if I understand correctly) is that, in the has_inc_and_crpt case, the value of has_inc_function is first evaluated to determine the default value for the Childs second template parameter
template<class Child, bool = has_inc_function<Child, void>::value>
struct base
that is when Child (that is has_inc_and_crpt) is still incomplete, so the value if false, and in the following use
static_assert(has_inc_function<has_inc_and_crtp, void>::value == true, "");
remain false.
How would I implement has_inc_function so that it works as I would expect in all these test case, or is what I want just not possible?
A quick and dirty solution could be add an additional dummy defaulted template parameter to has_inc_function.
By example
// ................................VVVVVVV dummy and defaulted
template <typename C, typename RT, int = 0>
struct has_inc_function
then use it in base explicating a special (different from the default) parameter
// ........................................................V different from the default
template<class Child, bool = has_inc_function<Child, void, 1>::value>
struct base
So, when you use has_inc_functin in the static assert,
static_assert(has_inc_function<has_inc_and_crtp, void>::value == true, "");
the class is different, is evaluated in that moment and has_inc_and_crpt is detected with inc() method.
But this only resolve the problem at test case (static_assert()) level.
Still remain the problem (a problem that I don't how to solve) that, declaring base, the default value remain false. So (I suppose) has_inc_and_crpt still select the wrong base base.
The following is a full compiling example, following the jrok's solution.
#include <type_traits>
template <typename C, typename RT, int = 0>
struct has_inc_function
{
private:
template <typename T>
static constexpr auto check(T *) ->
typename std::is_same<decltype(std::declval<T>().inc()), RT>::type;
template <typename>
static constexpr std::false_type check(...);
using type = decltype(check<C>(nullptr));
public:
/// #brief True if there is an inc member function
static constexpr bool value = type::value;
};
template <typename Child, bool = has_inc_function<Child, void, 1>::value>
struct base
{ };
template <typename Child>
struct base<Child, true>
{ };
struct empty : public base<empty>
{ };
struct has_inc
{ void inc() {} };
struct has_inc_and_crtp : public base<has_inc_and_crtp>
{ void inc() {} };
struct has_inc_and_misuse_crtp : public base<has_inc_and_misuse_crtp, true>
{ void inc() {} };
struct has_inc_and_misuse_crtp2 : public base<has_inc_and_misuse_crtp, false>
{ void inc() {} };
struct no_inc_and_misuse_crtp : public base<no_inc_and_misuse_crtp, true>
{ };
template <typename C, typename RT>
constexpr auto hif_v = has_inc_function<C, RT>::value;
int main ()
{
static_assert(hif_v<empty, void> == false, "");
static_assert(hif_v<has_inc, void> == true, "");
static_assert(hif_v<has_inc_and_crtp, void> == true, "");
static_assert(hif_v<has_inc_and_misuse_crtp, void> == true, "");
static_assert(hif_v<has_inc_and_misuse_crtp2, void> == true, "");
static_assert(hif_v<no_inc_and_misuse_crtp, void> == false, "");
}

Define a templete class only using bool and char

I intended to have a class that only specifically dealing with bool or char type without using boost. My code is as below and I am using VS2017 Community:
#include <type_traits>
template<typename T,
typename std::enable_if_t<
std::is_same<T, bool>::value || std::is_same<T, char>::value >::type >
class BoolAndCharData
{
public:
BoolAndCharData(const T& _data) {...}
void DoSomething() {...}
}; // end of class BoolAndCharData
int main()
{
char c;
BoolAndCharData<char> data(c); // error C2976: too few template parameter
....
} // end of main()
I tried the other way as someone presented in this site, compiler said it couldn't recognize the template:
template<typename T>
class BoolAndCharData<T,
typename std::enable_if_t< std::is_same<T, bool>::value ||
std::is_same<T, char>::value >::type >
{
public:
BoolAndCharData(const T& _data) {...}
void DoSomething() {...}
}; // end of class BoolAndCharData
I have browsed through this site and other webs for a few hours and found although there are quite some discussions over restricting template type, most either using boots or specific for a function. I still can't get it clear how to write a template class with selected data type. Can someone kindly point the way to rescue me from blindly trying ?
You don't need to use std::enable_if_t to do that. A static_assert is enough in this case.
As a minimal, working example:
#include <type_traits>
template<typename T>
class BoolAndCharData {
static_assert(std::is_same<T, bool>::value or std::is_same<T, char>::value, "!");
public:
BoolAndCharData(const T& _data) {}
void DoSomething() {}
};
int main() {
char c;
BoolAndCharData<char> d1(c);
// the following line won't compile
// BoolAndCharData<int> d2(0);
// ...
}
See it on Coliru. Errors when using static_assert are also nicer than what you get out usually from templates.
A possible solution is the following
template <typename, typename = void>
class BoolAndCharData;
template <typename T>
class BoolAndCharData<T, std::enable_if_t<
std::is_same<T, bool>::value || std::is_same<T, char>::value > >
{
public:
BoolAndCharData(const T& _data)
{}
void DoSomething()
{}
};
A little variation on the theme is define a specific type-traits
template <typename, typename = void>
struct boolOrChar
{ };
template <typename T>
struct boolOrChar<bool, T>
{ using type = T; };
template <typename T>
struct boolOrChar<char, T>
{ using type = T; };
so BoolAndCharData can be written as
template <typename, typename = void>
class BoolAndCharData;
template <typename T>
class BoolAndCharData<T, typename boolOrChar<T>::type>
{
public:
BoolAndCharData(const T& _data)
{}
void DoSomething()
{}
};
You can use template specialization, together with inheritance for the common code:
// Declares the generic case
template<typename T>
struct BoolAndCharData;
// Common base-class for the common code
template<typename T>
struct BoolAndCharDataCommon
{
explicit BoolAndCharDataCommon(T) {}
void DoSomething() {}
};
// Specialization for the char data-type
template<>
struct BoolAndCharData<char> : public BoolAndCharDataCommon<char>
{
// To use the constructor(s) from the base class
using BoolAndCharDataCommon::BoolAndCharDataCommon;
};
// Specialization for the bool data-type
template<>
struct BoolAndCharData<bool> : public BoolAndCharDataCommon<bool>
{
// To use the constructor(s) from the base class
using BoolAndCharDataCommon::BoolAndCharDataCommon;
};
int main()
{
BoolAndCharData<char> a('a');
BoolAndCharData<bool> b(false);
a.DoSomething();
b.DoSomething();
// This will lead to a compiler error
BoolAndCharData<int> c;
}
This way makes it easy to collect all common code, but also very easy to add code that is specific for the specific types if that's needed.

How can I check whether a member function has const overload?

Lets say I have
struct foo {
void ham() {}
void ham() const {}
};
struct bar {
void ham() {}
};
Assuming I have a templated function, can I tell whether given type has a const overload for ham?
With
#define DEFINE_HAS_SIGNATURE(traitsName, funcName, signature) \
template <typename U> \
class traitsName \
{ \
private: \
template<typename T, T> struct helper; \
template<typename T> \
static std::uint8_t check(helper<signature, &funcName>*); \
template<typename T> static std::uint16_t check(...); \
public: \
static \
constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t); \
}
DEFINE_HAS_SIGNATURE(has_ham_const, T::ham, void (T::*)() const);
And then
static_assert(has_ham_const<foo>::value, "unexpected");
static_assert(!has_ham_const<bar>::value, "unexpected");
Demo
SFINAE over and over again. Here is another option which is unspecified about the return types but lets you specify the arguments.
(For comparison: the approach by #Jarod42 checks the exact signature, return type + arguments, the other void_t expression sfinae stuff up to now checks only whether ham() can be called.)
Plus, it works with the current MSVC 2015 Update 1 version (unlike the usual void_t stuff).
template<typename V, typename ... Args>
struct is_callable_impl
{
template<typename C> static constexpr auto test(int) -> decltype(std::declval<C>().ham(std::declval<Args>() ...), bool{}) { return true; }
template<typename> static constexpr auto test(...) { return false; }
static constexpr bool value = test<V>(int{});
using type = std::integral_constant<bool, value>;
};
template<typename ... Args>
using is_callable = typename is_callable_impl<Args...>::type;
Use it as
struct foo
{
void ham() {}
void ham() const {}
int ham(int) const {}
};
int main()
{
std::cout
<<is_callable<foo>::value //true
<<is_callable<const foo>::value //true
<<is_callable<const foo, int>::value //true
<<is_callable<const foo, double>::value //also true, double is converted to int
<<is_callable<const foo, std::string>::value //false, can't call foo::ham(std::string) const
<<std::endl;
}
Demo on Coliru
For the "newest" sfinae stuff, however, I suggest you have a look at boost.hana.
Detector (like is_detected):
template <typename...>
using void_t = void;
template <typename T, template <typename> class D, typename = void>
struct detect : std::false_type {};
template <typename T, template <typename> class D>
struct detect<T, D, void_t<D<T>>> : std::true_type {};
Sample member verifier:
template <typename T>
using const_ham = decltype(std::declval<const T&>().ham());
Test:
static_assert(detect<foo, const_ham>::value, "!");
static_assert(!detect<bar, const_ham>::value, "!");
DEMO
Another option is to simulate void_t(to appear officially in C++17), which makes use of expression SFINAE to make sure your function is call-able on a const instance, regardless of its return type.
#include <iostream>
#include <type_traits>
struct Foo
{
void ham() const;
void ham();
};
struct Bar {
void ham() {}
};
template<typename...>
using void_t = void;
template<typename C, typename = void>
struct has_const_ham: std::false_type{};
template<typename C> // specialization, instantiated when there is ham() const
struct has_const_ham<C, void_t<decltype(std::declval<const C&>().ham())>> :
std::true_type{};
int main()
{
std::cout << std::boolalpha;
std::cout << has_const_ham<Foo>::value << std::endl;
std::cout << has_const_ham<Bar>::value << std::endl;
}
EDIT
If you want to enforce the return type, then derive the specialization from std::is_same, like
template<typename C> // specialization, instantiated when there is ham() const
struct has_const_ham<C, void_t<decltype(std::declval<const C&>().ham())>> :
std::is_same<decltype(std::declval<const C&>().ham()), void> // return must be void
{};
Live on Coliru
Here is a solution without macros which also does not care about return types:
template <typename T>
struct is_well_formed : std::true_type
{
};
template <typename T, typename = void>
struct has_const_ham : std::false_type
{
};
template <typename T>
struct has_const_ham<T,
typename std::enable_if<is_well_formed<decltype(
std::declval<const T&>().ham())>::value>::type>
: std::true_type
{
};
static_assert(has_const_ham<foo>::value, "oops foo");
static_assert(!has_const_ham<bar>::value, "oops bar");

Testing whether a function is virtual [duplicate]

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 ?
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.