I've got a templated class that looks like this:
template<typename T>
class TemplatedClass
{
// ... Other functions
void AssignTo(const T & value)
{
m_value = value;
}
private:
T m_value;
// ...
}
that I want to work with std::atomic<>, but doesn't at the moment because std::atomic<> is non-copyable.
Is there any way to only re-implement the AssignTo() function, but keep using all the other functions without modification so that we can have e.g. TemplatedClass<std::atomic<bool>? I've thought about using std::enable_if or template specialization, but haven't come up with an elegant solution.
#include <type_traits>
template <typename T>
class TemplatedClass
{
public:
void AssignTo(const T& value)
{
if constexpr (std::is_copy_assignable_v<T>) {
m_value = value;
} else {
// Something else
}
}
private:
T m_value;
};
DEMO
For atomic-only types, replace std::is_copy_assignable_v<T> with !is_atomic_v<T>:
template <typename>
constexpr bool is_atomic_v = false;
template <typename T>
constexpr bool is_atomic_v<std::atomic<T>> = true;
Is there any way to only re-implement the AssignTo() function, but keep using all the other functions without modification so that we can have e.g. TemplatedClass<std::atomic<bool>?
Do you mean something as follows?
template <typename>
struct isAtomic : public std::false_type
{ };
template <typename T>
struct isAtomic<std::atomic<T>> : public std::true_type
{ };
template <typename T>
constexpr auto isAtomic_v = isAtomic<T>::value;
template <typename T>
class TemplatedClass
{
public:
// ... Other functions
template <typename U = T>
std::enable_if_t<false == isAtomic_v<U>> AssignTo(const T & value)
{ m_value = value; }
template <typename U = T>
std::enable_if_t<true == isAtomic_v<U>> AssignTo(const T & value)
{ /* ??? */ }
private:
T m_value;
// ...
};
Related
Let's say I have small library that I want to wrap in order to improve usability. I only want to wrapper them; I don't want to touch the existing code.
For example:
template <typename T>
class vector_type_A {
//...
};
template <typename T>
class vector_type_B {
//...
};
template <typename T>
class vector_type_C {
//...
};
I can do this to wrap a class:
enum type_e {
Type_A, Type_B, Type_C
};
template <type_e type, typename T>
class vector_selector;
template <typename T>
class vector_selector <Type_A, T> {
public:
using vector = vector_type_A<T>;
};
template <typename T>
class vector_selector <Type_B, T> {
public:
using vector = vector_type_B<T>;
};
template <typename T>
class vector_selector <Type_C, T> {
public:
using vector = vector_type_C<T>;
};
template <type_e type, typename T>
using vector = typename vector_selector<type,T>::vector;
But this doesn't wrap functions, only classes.
How can I write similar selector for functions?
This would be easy if we could partially specialize function templates, but we can't, so we need to use a class to do this.
Given your functions (as an example):
template<typename T>
int fn_type_A(vector_type_A<T> const&) {
return 0;
}
template<typename T>
int fn_type_B(vector_type_B<T> const&) {
return 1;
}
template<typename T>
int fn_type_C(vector_type_C<T> const&) {
return 2;
}
You can write this:
template<type_e type>
struct fn_selector;
template<>
struct fn_selector<Type_A>
{
template<typename T>
static int fn(vector_type_A<T> const& vec) {
return fn_type_A(vec);
}
};
template<>
struct fn_selector<Type_B>
{
template<typename T>
static int fn(vector_type_B<T> const& vec) {
return fn_type_B(vec);
}
};
template<>
struct fn_selector<Type_C>
{
template<typename T>
static int fn(vector_type_C<T> const& vec) {
return fn_type_C(vec);
}
};
template<type_e type, typename T>
int fn(vector<type, T> const& vec) {
return fn_selector<type>::fn(vec);
}
If you find that you are writing many of these, you should probably combine them into a single selector:
template<type_e>
struct vector_selector;
template<>
struct vector_selector<Type_A>
{
template<typename T>
using type = vector_type_A<T>;
template<typename T>
static int fn(vector_type_A<T> const& vec) {
return fn_type_A(vec);
}
};
template<>
struct vector_selector<Type_B>
{
template<typename T>
using type = vector_type_B<T>;
template<typename T>
static int fn(vector_type_B<T> const& vec) {
return fn_type_B(vec);
}
};
template<>
struct vector_selector<Type_C>
{
template<typename T>
using type = vector_type_C<T>;
template<typename T>
static int fn(vector_type_C<T> const& vec) {
return fn_type_C(vec);
}
};
template <type_e type, typename T>
using vector = typename vector_selector<type>::template type<T>;
template<type_e type, typename T>
int fn(vector<type, T> const& vec) {
return vector_selector<type>::fn(vec);
}
With C++17, you could simplify the function selection to:
template<type_e type, typename T>
int fn(vector<type, T> const& vec) {
if constexpr (type == Type_A) {
return fn_type_A(vec);
} else if (type == Type_B) {
return fn_type_B(vec);
} else {
static_assert(type == Type_C, "Unknown type");
return fn_type_C(vec);
}
}
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 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;
};
I'm doing some template meta programming and I have a situation like this, first I have a few classes like :-
template <typename Q>
struct Object {
public:
Q data;
};
template <typename P>
class CircleObject : public Object<const typename P::Circle> {
};
template <typename P>
class SquareObject : public Object<const typename P::Circle> {
};
template <typename P>
class Storage {
public:
typedef CircleObject<P> MyCircle;
typedef SquareObject<P> MySquare;
};
Now, I'm trying to define some traits of these objects as such :-
template <typename P>
struct CircleTraits<Storage<P> > {
template <typename otype>
struct IsCircle {
static const bool VALUE = false;
};
};
template <typename P>
struct CircleTraits<Storage<P> >::IsCircle<Storage<P>::MyCirlce> {
static const bool VALUE = true;
};
However, this is incorrect (compile errors). I've tried a trial and error method of putting typenames and template parameters everywhere but without a firm understanding of template specializations, I'm not really able to fix this. Can someone help here?
What I'm hoping to achieve in a later function is something like :-
typedef Storage<RedObjects> RedStorage;
template <typename SpecializedStorage>
class Processor {
typedef CircleTraits<typename SpecializedStorage> MyCircleTraits;
template <typename ObjectType>
void foo(ObjectType& data);
};
template <typename SpecializedStorage>
template <typename ObjectType>
void foo(ObjectType& data) {
if (MyCircleTraits::template IsCircle<ObjectType>::VALUE) {
// do something about the damn circles
}
}
I think you cant do it like that, You probably should use SFINAE to solve something like this:
//C++11 version
template<typename T>
struct IsCircle
{
private:
template<typename Z>
constexpr static bool _is(typename Z::MyCirlce*) //if Z dont have `MyCirlce` then this function is removed
{
return true;
}
template<typename Z>
constexpr static bool _is(...) //fallback function
{
return false;
}
public:
static const bool VALUE = _is<T>(nullptr);
};
//C++98 version
template<typename T>
struct IsCircle
{
private:
struct a { char a; }; //size ~1
struct b { char a[8]; }; //size ~8
template<typename Z>
static b _is(typename Z::MyCirlce*);
template<typename Z>
static a _is(...);
public:
static const bool VALUE = sizeof(_is<T>(0)) == sizeof(b);
};
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.