I'm currently creating a template container class in which I like to have a sorting ability whenever the template class has the comparison operator.
With SFINAE I can determine if the operator exist during runtime. However, when compiling the code below it of course still tries to compile the line containing sort, which will return compiler errors if the compare operator is not specified for that class.
Is there a way to 'avoid' compiling that line if the comparison operator doesn't exist? Not knowing the naming of such procedure, something like an '#ifdef SFINAE'?
template <class UseClass> class Container {
public:
bool Sort(void) {
if (CHECK::opCompareExists<UseClass>::value) {
sort(m_classlist.begin(),m_classlist.end()); //compile error, of course
return true;
}
return false;
}
private:
vector<UseClass> m_classlist;
};
Maybe I shouldn't use SFINAE at all... maybe it should be a template specification? How would that work (based on automatic detection that the operator is not present)?
std::sort() by default uses the less-than operator (operator<()) to compare elements so you can simply use expression SFINAE to rule out a specific overload if the type doesn't have it:
template<typename T = UseClass>
auto Sort() -> decltype(std::declval<T>() < std::declval<T>(), bool())
{
return true;
}
If substitution fails (SomeClass does not have operator<()) then compilation will fail.
If this wasn't your intention, and instead you wanted to return true if it could sort and false otherwise, then you need a trait class that you can overload based on:
namespace detail
{
template<typename T>
auto has_less_than_impl(int)
-> decltype(std::declval<T>() < std::declval<T>(), std::true_type());
template<typename>
std::false_type has_less_than_impl(...);
}
template<typename T>
struct has_less_than : decltype(detail::has_less_than_impl<T>(0)) { };
template <class UseClass> class Container
{
public:
bool Sort() { return Sort(has_less_than<UseClass>::value); }
private:
bool Sort(std::true_type)
{
sort(m_classlist.begin(), m_classlist.end());
return true;
}
bool Sort(std::false_type) { return false; }
};
Update: As per your comment here is a C++03 implementation:
template <typename T>
class has_less_than {
struct Fallback { bool operator<(T const&); };
struct Derived : T, Fallback {};
template <typename U, U> struct S;
template <typename C> static char (&f(S<bool (Fallback::*)(T const&), &C::operator<>*))[1];
template <typename C> static char (&f(...))[2];
public:
const static bool value = sizeof(f<Derived>(0)) == 2;
};
namespace detail
{
template <bool B, typename R = void>
struct enable_if { typedef R type; };
template <typename R>
struct enable_if<false, R> { };
}
template <class UseClass> class Container {
public:
bool Sort() { return Sort<UseClass>(); }
private:
template <typename T>
bool Sort(typename detail::enable_if<has_less_than<T>::value, int>::type = 0) {
sort(m_classlist.begin(),m_classlist.end());
return true;
}
template <typename T>
bool Sort(typename detail::enable_if<!has_less_than<T>::value, int>::type = 0) {
return false;
}
private:
vector<UseClass> m_classlist;
};
Related
I have a template Matrix class and I used a std::vector<std::vector<T>> to store data.
I need to specialize some methods for std::complex matrix, for example:
template <typename T>
bool Matrix<T>::is_hermitian() const
{
if (!(*this).is_squared())
return false;
for (int r = 0; r < rows_; r++)
for (int c = 0; c < columns_; c++)
if (mat[r][c] != mat[c][r])
return false;
return true;
}
For the specialized method I thought something like this:
template <typename T>
bool Matrix<std::complex<T> >::is_hermitian() const
{
if (!(*this).is_squared())
return false;
for (int r = 0; r < rows_; r++)
for (int c = 0; c < columns_; c++)
if (mat[r][c] != std::conj(mat[c][r]))
return false;
return true;
}
But the compiler returns me an error
'invalid use of incomplete type'
I instantiated at the end of the .cpp file a bunch of class that I could be using in the main program:
template class Matrix<int>;
template class Matrix<double>;
template class Matrix<float>;
template class Matrix< std::complex<float> >;
template class Matrix< std::complex<int> >;
How can I implement one method for all std::complex<T> type?
And if you know how to replace the last two instance with a Matrix< std::complex<T> > sort of thing I will be very thankful.
You can apply SFINE(i.e."Substitution Failure Is Not An Error") technique along with function overloading to choose the correct method when T is std::complex in Matrix<T> class instatiation.
Following is the demonstration of the idea: (See example code online live)
#include <type_traits> // std::enable_if, std::false_type
// traits for checking, T is `std::complex`
template<typename> struct is_std_complex : std::false_type {};
template<typename T> struct is_std_complex<std::complex<T>> : std::true_type {};
// traits for `std::enable_if` helpers
template<typename Type, typename ReType = void>
using EnabledForComplex = typename std::enable_if<is_std_complex<Type>::value, ReType>::type;
template<typename Type, typename ReType = void>
using EnabledNotForComplex = typename std::enable_if<!is_std_complex<Type>::value, ReType>::type;
template<typename T>
class Matrix
{
// ...members
public:
template<typename Type = T>
auto is_hermitian() const -> EnabledNotForComplex<Type, bool>
{
// ... code for non-std::complex types
}
template<typename Type = T>
auto is_hermitian() const->EnabledForComplex<Type, bool>
{
// ... code for std::complex types
}
};
That being said, if you have access to c++17, you could use if constexpr, which will only instantiate the branch, which is true for the case at compile time. (See example code online live)
#include <type_traits> // std::false_type
// traits for checking, T is `std::complex`
template<typename> struct is_std_complex : std::false_type {};
template<typename T> struct is_std_complex<std::complex<T>> : std::true_type {};
template<typename T>
class Matrix
{
// ...members
public:
bool is_hermitian() const
{
if (!is_squared()) return false;
if constexpr (is_std_complex<T>::value)
{
// ... code for std::complex types
}
else
{
// ... code for non-std::complex types
}
return true;
}
};
You cannot partially specialize function templates, but you can class templates. One trick is to have the member function delegate to a helper class template. Something like this:
template <typename T>
struct IsHermitianHelper;
template <typename T>
class Matrix {
friend class IsHermitianHelper<T>;
public:
bool is_hermitian() const;
};
template <typename T>
struct IsHermitianHelper {
static bool is_hermitian(const Matrix<T>& m) {
// General implementation here
}
};
template <typename T>
struct IsHermitianHelper<std::complex<T>> {
static bool is_hermitian(const Matrix<std::complex<T>>& m) {
// Special case for std::complex here
}
};
template <typename T>
bool Matrix<T>::is_hermitian() const {
return IsHermitianHelper<T>::is_hermitian(*this);
}
I want to be able to customize handling of a struct based on the presence of a type within the struct (without writing any additional code per custom struct), like:
struct Normal_t
{
};
struct Custom_t
{
using my_custom_type = bool;
};
It seems like I should be able to do something like this, but it doesn't work:
template <class T, typename Enabler = void>
struct has_custom_type
{
bool operator()() { return false; }
};
template <class T>
struct has_custom_type<T, typename T::my_custom_type>
{
bool operator()() { return true; }
};
bool b_normal = has_custom_type<Normal_t>()(); // returns false
bool b_custom = has_custom_type<Custom_t>()(); // returns false, INCORRECT? should return true?
What I don't understand is that the standard library uses something similar but seemingly more convoluted for its type traits. For example, this works:
template<bool test, class T = void>
struct my_enable_if
{
};
template<class T>
struct my_enable_if<true, T>
{
using type = T;
};
template <class T, class Enabler = void>
struct foo
{
bool operator()() { return false; }
};
template <class T>
struct foo<T, typename my_enable_if<std::is_integral<T>::value>::type>
{
bool operator()() { return true; }
};
bool foo_float = foo<float>()(); // returns false
bool foo_int = foo<int>()(); // returns true
In both cases, the specialization is happening based on the presence of a type within a struct, in one case typename T::my_custom_type and in the other typename my_enable_if<std::is_integral<T>::value>::type. Why does the second version work but not the first?
I came up with this workaround using the ... parameter pack syntax, but I'd really like to understand if there is a way to do this using normal template specialization without using the parameter pack syntax, and if not, why.
template<typename ...Args>
bool has_custom_type_2(Args&& ...args) { return false; }
template<class T, std::size_t = sizeof(T::my_custom_type)>
bool has_custom_type_2(T&) { return true; }
template<class T, std::size_t = sizeof(T::my_custom_type)>
bool has_custom_type_2(T&&) { return true; } /* Need this T&& version to handle has_custom_type_2(SomeClass()) where the parameter is an rvalue */
bool b2_normal = has_custom_type_2(Normal_t()); // returns false
bool b2_custom = has_custom_type_2(Custom_t()); // returns true - CORRECT!
The problem is that you specify default void type for Enabler, but T::my_custom_type is not void. Either use bool as default type, or use std::void_t that always returns void:
template <class T, typename = void>
struct has_custom_type : std::false_type { };
template <class T>
struct has_custom_type<T, std::void_t<typename T::my_custom_type>> : std::true_type { };
This answer explains why types should match.
As explained by others, if you set a void default value for the second template parameter, your solution works only if my_custom_type is void.
If my_custom_type is bool, you can set bool the default value. But isn't a great solution because loose generality.
To be more general, you can use SFINAE through something that fail if my_custom_type doesn't exist but return ever the same type (void, usually) if my_custom_type is present.
Pre C++17 you can use decltype(), std::declval and the power of comma operator
template <class T, typename Enabler = void>
struct has_custom_type
{ bool operator()() { return false; } };
template <class T>
struct has_custom_type<T,
decltype( std::declval<typename T::my_custom_type>(), void() )>
{ bool operator()() { return true; } };
Starting from C++17 it's simpler because you can use std::void_t (see Evg's answer, also for the use of std::true_type and std::false_type instead of defining an operator()).
template <class T, typename Enabler = void> // <== void set as default template parameter type
struct has_custom_type
{
bool operator()() { return false; }
};
template <class T>
struct has_custom_type<T, typename T::my_custom_type>
{
bool operator()() { return true; }
};
The specialization matches when it gets the template parameters <T, bool>. However, when you just specify <T>, without a second type, then it goes to the default type you specified =void to come up with the call <T, void>, which doesn't match your bool specialization.
Live example showing it matches with explicit <T, bool>: https://godbolt.org/z/MEJvwT
This is more of a curiosity with C++ templates than something useful. It supposed to be a class with a variable number of members. Is it likely that this will be compiled down to direct member access?
// type equality
template <typename X, typename Y> struct Eq { static const bool out = false; };
template <typename X> struct Eq<X, X> { static const bool out = true; };
template <typename First, typename... Rest>
class Table {
First _field;
Table<Rest...> _nextTable;
public:
template <typename T>
T &get() {
if (Eq<First, T>::out)
return (T&)_field;
return (T&)_nextTable.get<T>();
}
};
template<typename First>
class Table<First> {
First _field;
public:
template <typename T>
T &get() {
return _field;
}
};
int main() {
Table<int, double> table;
table.get<double>() = 11.1;
}
return (T&)_nextTable.template get<T>();
http://en.cppreference.com/w/cpp/language/dependent_name
I'm trying to write code that is effectively:
template <typename... Mixins>
class Checker : public Mixins... {
public:
template<typename... Args>
Checker(Args&&... args) : Mixins(std::forward<Args>(args))... { }
bool check(void) {
bool tests = true;
// TODO: for each Mixins that has Mixin::check
{
tests = tests && Mixin::check();
}
if (!tests) {
// TODO: for each Mixin that has Mixin::handle
{
Mixin::handle()
}
}
return tests
}
};
I just don't know how to do the loops over just those Mixins satisfying the member conditions specified. I've tried various solutions for iteration and for enable_if type semantics but nothing seems to compile.
Additional
So, what I've tried so far visa vi for-each base recursion and SFINAE function elimination is the following, which doesn't compile:
template <typename C, typename... Mx>
struct do_checks;
template <typename C>
struct do_checks<C> {
static bool check(C *) {
return true;
}
};
template <typename C, typename E, typename... Mx>
struct do_checks<C, E, Mx...> {
struct general_ { };
struct special_ : general_ { };
template <typename> struct int_ { typedef int type; };
template <typename F, typename int_<decltype(F::check)>::type = 0>
static bool check(C *ptr, special_) {
if (!ptr->F::check()) {
return false;
}
return do_checks<C, Mx...>::check(ptr);
}
template <typename F>
static bool check(C *ptr, general_) {
return do_checks<C, Mx...>::check(ptr);
}
};
Where F should be E. I don't know how to tell the compiler to compile the first "check" if the int_ has a type and the second if it doesn't.
You can create a trait named has_check which returns true for a type which has a static check() method.
namespace detail
{
template<class T, class = decltype(T::check())>
std::true_type has_check_impl(void*);
template<class T>
std::false_type has_check_impl(...);
}
template<class T>
struct has_check : decltype(detail::has_check_impl<T>(nullptr)) { };
Then you can use it as the predicate to std::enable_if to enable/disable the overload if it has the method:
private:
template<class T, class...>
using first = T;
template<class T = void,
class =
first<T,
typename std::enable_if<has_check<Mixins>::value, T>::type...>>
static void foo(void*)
{
auto x{ (0, Mixins::check(), 0)... };
(void)x;
}
static void foo(...)
{
auto x{ (0, Mixins::handle(), 0)... };
(void)x;
}
public:
static void check() {
foo(nullptr);
}
I want to implement is_pointer. I want something like this:
template <typename T >
bool is_pointer( T t )
{
// implementation
} // return true or false
int a;
char *c;
SomeClass sc;
someAnotherClass *sac;
is_pointer( a ); // return false
is_pointer( c ); // return true
is_pointer( sc ); // return false
is_pointer( sac ); // return true
How can I implement it?
Thanks
template <typename T>
struct is_pointer_type
{
enum { value = false };
};
template <typename T>
struct is_pointer_type<T*>
{
enum { value = true };
};
template <typename T>
bool is_pointer(const T&)
{
return is_pointer_type<T>::value;
}
Johannes noted:
This is actually missing specializations for T *const, T *volatile and T * const volatile i think.
Solution:
template <typename T>
struct remove_const
{
typedef T type;
};
template <typename T>
struct remove_const<const T>
{
typedef T type;
};
template <typename T>
struct remove_volatile
{
typedef T type;
};
template <typename T>
struct remove_volatile<volatile T>
{
typedef T type;
};
template <typename T>
struct remove_cv : remove_const<typename remove_volatile<T>::type> {};
template <typename T>
struct is_unqualified_pointer
{
enum { value = false };
};
template <typename T>
struct is_unqualified_pointer<T*>
{
enum { value = true };
};
template <typename T>
struct is_pointer_type : is_unqualified_pointer<typename remove_cv<T>::type> {};
template <typename T>
bool is_pointer(const T&)
{
return is_pointer_type<T>::value;
}
...but of course this is just reinventing the std::type_traits wheel, more or less :)
From Dr. Dobbs.
template <typename T>
struct is_pointer
{ static const bool value = false; };
template <typename T>
struct is_pointer<T*>
{ static const bool value = true; };
You can't do exactly what you want to do. You'll have to use this like:
is_pointer<int*>::value
It's not possible to determine this at run time.
template <typename T>
bool is_pointer(T const &t) // edited: was "T t"; see the comments
{
return false;
}
template <typename T>
bool is_pointer(T *t)
{
return true;
}
You might not believe it, but it works. The reason is that the most specific template implementation will be chosen, which is the one which takes the pointer type.
You can use "typeid" operator defined in typeinfo.h for this.
check this link : http://en.wikipedia.org/wiki/Typeid
The typeid operator will give an object of std::type_info class, which has a name() function returning char *. Once you get the type in string form, you can identify the pointer easily.
Hope it helps.
Romil.