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
Related
Consider the class template:
template<typename T>
struct A
{
T data;
static const bool flag;
static bool calc_flag()
{
// Default value;
return false;
}
};
template<typename T>
const bool A<T>::flag = A<T>::calc_flag();
And now I'd like to specialize this template for the following class template:
template<char N>
struct B
{
static const bool is_a;
};
template<char N>
const bool B<N>::is_a = N == 'a';
in order to the A<B<N>>::flag will be initialized with the B<N>::is_a. I.e., I'd like to specialize the calc_flag() method for such the case. How could this be done?
You could separate the calculation to an implementation struct and only specialize that
template<class T>
struct calc_flag_impl {
static bool calc_flag() { return false; }
};
template<typename T>
struct A
{
T data;
static const bool flag = calc_flag_impl<T>::calc_flag();
};
Now you can specialize calc_flag_impl
template<char N>
struct calc_flag_impl<B<N>> {
static bool calc_flag() { return B<N>::is_a; }
};
Note: The specialization must exist prior to instantiation of the class template for your type for it to work with static class variables.
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;
// ...
};
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);
}
}
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'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);
}