How to check whether operator== exists?
C++03
The following trick works and it can be used for all such operators:
namespace CHECK
{
class No { bool b[2]; };
template<typename T, typename Arg> No operator== (const T&, const Arg&);
bool Check (...);
No& Check (const No&);
template <typename T, typename Arg = T>
struct EqualExists
{
enum { value = (sizeof(Check(*(T*)(0) == *(Arg*)(0))) != sizeof(No)) };
};
}
Usage:
CHECK::EqualExists<A>::value;
The 2nd template typename Arg
is useful for some special cases like A::operator==(short)
, where it's not similar to class
itself. In such cases the usage is:
CHECK::EqualExists<A, short>::value
// ^^^^^ argument of `operator==`
Demo.
C++11
We need not use sizeof
and null reference trick when we have decltype
and std::declval
namespace CHECK
{
struct No {};
template<typename T, typename Arg> No operator== (const T&, const Arg&);
template<typename T, typename Arg = T>
struct EqualExists
{
enum { value = !std::is_same<decltype(std::declval<T>() < std::declval<Arg>()), No>::value };
};
}
Demo
How to use sfinae to check, whether type has operator ()?
Encouraged by a positive feedback, I will post a brief answer here.
The problem is that you cannot define a class twice, but you did this two times :-
template <typename T>
struct function_traits { .... some code ..... }
C++ doesn't allow that.
To check whether a function is exist, there is already a question about it, you can modify it to support the operator()
.
Here is a demo, very-slightly modified from Nicola Bonelli's answer there.
#include <iostream>
struct Hello
{
void operator()() { }
};
struct Generic {};
// SFINAE test
template <typename T>
class has_parenthesis
{
typedef char one;
typedef long two;
template <typename C> static one test( decltype(&C::operator()) ) ;
template <typename C> static two test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(char) };
};
int main(int argc, char *argv[])
{
std::cout << has_parenthesis<Hello>::value << std::endl; //print 1
std::cout << has_parenthesis<Generic>::value << std::endl; //print 0
return 0;
}
I just knew a few minutes ago that it also works for operator()
.
Edit: I changed typeof
to decltype
as StoryTeller and LmTinyToon recommended. Thank.
best way to check for existence of an operator in c++11
Quick-and-dirty C++11 SFINAE:
template<typename T,
typename = decltype(
std::declval<std::ostream&>() << std::declval<T const&>()
)
>
std::string toString(T const& t)
{
std::ostringstream out;
// Beware of no error checking here
out << t;
return out.str();
}
template<typename T,
typename... Ignored
>
std::string toString(T const& t, Ignored const&..., ...)
{
static_assert( sizeof...(Ignored) == 0
, "Incorrect usage: only one parameter allowed" );
/* handle any which way here */
}
If you want you can also check that the return type of stream << val
is indeed convertible to std::ostream&
:
template<typename T,
typename Result = decltype(
std::declval<std::ostream&>() << std::declval<T const&>()
),
typename std::enable_if<
std::is_convertible<Result, std::ostream&>::value,
int
>::type = 0
>
As for a not so quick-and-dirty solution I'd introduce an is_stream_insertable
trait, which implementation can make use of the very same tricks used here.
Be aware that std::integral_constant<bool, B>
has a conversion operator to bool
, this might explain some of the things you have observed. I also do not recommend mixing the C++11 Standard types and traits with Boost: don't mix up std::true_type
with boost::true_type
! Which is not to say that you shouldn't use e.g. Boost.TypeTraits at all with C++11, but try to be consistent and only use one of two at a time.
Is it possible to use SFINAE/templates to check if an operator exists?
I ended up using a fallback namespace :
namespace operators_fallback {
template <typename T>
inline QDataStream& operator<<(QDataStream& s, const T &) { return s; }
template <typename T>
inline QDataStream& operator>>(QDataStream& s, T &) { return s; }
template <typename T>
inline QDebug operator<<(QDebug d, const T &) { return d; }
};
...
inline void load(QDataStream & s) {
using namespace operator_fallback;
s >> item;
}
Also found the proper way to check for operators at compile time (although I'm going with the fallback namespace).
more or less based on this :
namespace private_impl {
typedef char yes;
typedef char (&no)[2];
struct anyx { template <class T> anyx(const T &); };
no operator << (const anyx &, const anyx &);
no operator >> (const anyx &, const anyx &);
template <class T> yes check(T const&);
no check(no);
template <typename StreamType, typename T>
struct has_loading_support {
static StreamType & stream;
static T & x;
static const bool value = sizeof(check(stream >> x)) == sizeof(yes);
};
template <typename StreamType, typename T>
struct has_saving_support {
static StreamType & stream;
static T & x;
static const bool value = sizeof(check(stream << x)) == sizeof(yes);
};
template <typename StreamType, typename T>
struct has_stream_operators {
static const bool can_load = has_loading_support<StreamType, T>::value;
static const bool can_save = has_saving_support<StreamType, T>::value;
static const bool value = can_load && can_save;
};
}
template<typename T>
struct supports_qdatastream : private_impl::has_stream_operators<QDataStream, T> {};
template<typename T>
struct can_load : private_impl::has_loading_support<QDataStream, T> {};
template<typename T>
struct can_save : private_impl::has_saving_support<QDataStream, T> {};
template<typename T>
struct can_debug : private_impl::has_saving_support<QDebug, T> {};
//edit changed has_stream_operators a bit.
//edit removed the link, apparently the site has some attack javascript.
does int have an operator==
int
is not a class-type and has no member operator==
, which is what you check for with your &C::operator==
. Thus, the test yields a "no". As others correctly pointed out, your test would also be negative for classes with only a non-member operator==
.
How to correctly check whether an operator==
exists has been asked here:
How to check whether operator== exists?
Check if class/struct has a specific operator
This kind of traits type almost always takes the following form:
#include <utility>
#include <iostream>
#include <string>
template<class T, class Arg>
struct has_equals_impl
{
template<class U> static
auto test(const U* p)
-> decltype( /* the test is here */
(*p) == std::declval<Arg>(),
/* end of test */
void(), std::true_type());
static auto test(...) -> std::false_type;
using type = decltype(test((const T*)nullptr));
};
// this typedef ensures that the actual type is either std::true_type or std::false_type
template<class T, class Arg> using has_equals = typename has_equals_impl<T, Arg>::type;
int main()
{
// int == int? yes
std::cout << has_equals<int, int>() << std::endl;
// string == int? no
std::cout << has_equals<std::string, int>() << std::endl;
}
Here is an almost-complete suite of binary operator checkers with some tests.
You should get the general idea. Note that I had to create left_shift
and right_shift
function objects since these don't exist in the standard library already.
#include <utility>
#include <iostream>
#include <string>
#include <algorithm>
#include <cassert>
template<class X, class Y, class Op>
struct op_valid_impl
{
template<class U, class L, class R>
static auto test(int) -> decltype(std::declval<U>()(std::declval<L>(), std::declval<R>()),
void(), std::true_type());
template<class U, class L, class R>
static auto test(...) -> std::false_type;
using type = decltype(test<Op, X, Y>(0));
};
template<class X, class Y, class Op> using op_valid = typename op_valid_impl<X, Y, Op>::type;
namespace notstd {
struct left_shift {
template <class L, class R>
constexpr auto operator()(L&& l, R&& r) const
noexcept(noexcept(std::forward<L>(l) << std::forward<R>(r)))
-> decltype(std::forward<L>(l) << std::forward<R>(r))
{
return std::forward<L>(l) << std::forward<R>(r);
}
};
struct right_shift {
template <class L, class R>
constexpr auto operator()(L&& l, R&& r) const
noexcept(noexcept(std::forward<L>(l) >> std::forward<R>(r)))
-> decltype(std::forward<L>(l) >> std::forward<R>(r))
{
return std::forward<L>(l) >> std::forward<R>(r);
}
};
}
template<class X, class Y> using has_equality = op_valid<X, Y, std::equal_to<>>;
template<class X, class Y> using has_inequality = op_valid<X, Y, std::not_equal_to<>>;
template<class X, class Y> using has_less_than = op_valid<X, Y, std::less<>>;
template<class X, class Y> using has_less_equal = op_valid<X, Y, std::less_equal<>>;
template<class X, class Y> using has_greater_than = op_valid<X, Y, std::greater<>>;
template<class X, class Y> using has_greater_equal = op_valid<X, Y, std::greater_equal<>>;
template<class X, class Y> using has_bit_xor = op_valid<X, Y, std::bit_xor<>>;
template<class X, class Y> using has_bit_or = op_valid<X, Y, std::bit_or<>>;
template<class X, class Y> using has_left_shift = op_valid<X, Y, notstd::left_shift>;
template<class X, class Y> using has_right_shift = op_valid<X, Y, notstd::right_shift>;
int main()
{
assert(( has_equality<int, int>() ));
assert((not has_equality<std::string&, int const&>()()));
assert((has_equality<std::string&, std::string const&>()()));
assert(( has_inequality<int, int>() ));
assert(( has_less_than<int, int>() ));
assert(( has_greater_than<int, int>() ));
assert(( has_left_shift<std::ostream&, int>() ));
assert(( has_left_shift<std::ostream&, int&>() ));
assert(( has_left_shift<std::ostream&, int const&>() ));
assert((not has_right_shift<std::istream&, int>()()));
assert((has_right_shift<std::istream&, int&>()()));
assert((not has_right_shift<std::istream&, int const&>()()));
}
is it possible to check if overloaded operator<< for type or class exists?
You could add trait (is_streamable
) like this:
#include <type_traits>
// A helper trait to check if the type supports streaming
template<class T>
class is_streamable {
// match if streaming is supported
template<class TT>
static auto test(int) ->
decltype( std::declval<std::ostream&>() << std::declval<TT>(), std::true_type() );
// match if streaming is not supported:
template<class>
static auto test(...) -> std::false_type;
public:
// check return value from the matching "test" overload:
static constexpr bool value = decltype(test<T>(0))::value;
};
template<class T>
inline constexpr bool is_streamable_v = is_streamable<T>::value;
You could then use it like this:
template<class T>
static void serialize_storage(const void* this_, std::ostream& stream) {
if constexpr (is_streamable_v<T>) {
stream << (*reinterpret_cast<const T*>(this_));
} else {
throw std::runtime_error("Type can not be serialized");
}
}
Demo
Check if an character is an operator
This line:
if (o == '%' || '/' || '*' || '+' || '-'){
should be:
if (o == '%' || o == '/' || o == '*' || o == '+' || o == '-'){
Related Topics
Incrementing in C++ - When to Use X++ or ++X
What's the Difference Between Std::Move and Std::Forward
Why Are Arrays of References Illegal
Error "Undefined Reference to 'Std::Cout'"
Why Aren't Pointers Initialized With Null by Default
Defining Static Const Integer Members in Class Definition
What Does It Mean to "Odr-Use" Something
What Is the Partial Ordering Procedure in Template Deduction
Tellg() Function Give Wrong Size of File
Capturing Stdout from a System() Command Optimally
C++: Catch a Divide by Zero Error
Is C++ Context-Free or Context-Sensitive
Dynamic_Cast and Static_Cast in C++
Proper Stack and Heap Usage in C++
How to Make Cmake Output into a 'Bin' Dir