Select appropriate function from enum - c++

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);
}
}

Related

c++ templates overloading method depend on class type

I have class like this:
template<typename T>
MyClass{
//myFunc();
}
I want to create myFunc method that return numeric value if class template is numeric and return nothing (void) when class template is not numeric.
For now, I got sth like this:
template<typename T>
MyClass{
template <typename returnT>
returnT myFunc();
}
template <typename T>
template <typename returnT>
typename std::enable_if<std::is_arithmetic<T>::value>
T MyClass<T>::myFunc()
{
return T::value;
}
template <typename T>
template <typename returnT>
typename std::enable_if<!std::is_arithmetic<T>::value>
void MyClass::myFunc()
{
//do sth
}
of course, that doesn't work. Is that a good idea to solve this problem this way? What is "smart" and working solution?
As an alternative to the constexpr if solution already supplied, here is your initial idea in it's working form.
#include <type_traits>
#include <iostream>
template<typename T>
struct MyClass{
template <typename returnT = T, std::enable_if_t<std::is_arithmetic_v<returnT>, bool> = true>
T myFunc();
template <typename returnT = T, std::enable_if_t<!std::is_arithmetic_v<returnT>, bool> = true>
void myFunc();
};
template <typename T>
template <typename returnT, std::enable_if_t<std::is_arithmetic_v<returnT>, bool>>
T MyClass<T>::myFunc()
{
std::cout << "yo\n";
return T{};
}
template <typename T>
template <typename returnT, std::enable_if_t<!std::is_arithmetic_v<returnT>, bool>>
void MyClass<T>::myFunc()
{
std::cout << "yay\n";
}
int main() {
MyClass<int> m;
MyClass<std::string> n;
m.myFunc();
n.myFunc();
}
The simplest way I can think of would be to just use if constexpr:
template <typename T>
class MyClass
{
auto myFunc()
{
if constexpr (std::is_arithmetic_v<T>)
{
return T{};
}
else
{
// do smth
}
}
};
If you can't use C++17, you will have to revert to some SFINAE-based approach. What that would best look like exactly depends a lot on what the actual signatures involved should be. But, for example, you could provide a partial class template specialization for the case of an arithmetic type:
template <typename T, typename = void>
class MyClass
{
void myFunc()
{
// do smth
}
};
template <typename T>
class MyClass<T, std::enable_if_t<std::is_arithmetic<T>::value>>
{
T myFunc()
{
return {};
}
};
Note that an arithmetic type cannot be a class type or enum, so I'm not sure what T::value was trying to achieve in your example code for the case of T being an arithmetic type…
I would create a helper template class to select the return type, and a helper function that uses overloading to perform the right behavior.
template <typename, bool> struct RType;
template <typename T> struct RType<T, false> { typedef void type; };
template <typename T> struct RType<T, true> { typedef T type; };
template<typename T>
class MyClass{
typedef RType<T, std::is_arithmetic<T>::value> R;
void myFuncT(RType<T, false>) {}
T myFuncT(RType<T, true>) { return 0; }
public:
typename R::type myFunc() { return myFuncT(R()); }
};

Class Template Specialization for one Function

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;
// ...
};

Template class with variable number of members in C++

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

Template function specialization for template class

Is it possible to write something like this in C++11/14?
#include <iostream>
#include <vector>
template <typename T>
T Get();
template <typename T>
struct Data {
std::vector<T> data;
};
template <>
template <typename T>
Data<T> Get<Data<T>>() {
return Data<T>{{T{}, T{}}};
}
template <>
template <typename T>
std::vector<T> Get<std::vector<T>>() {
return std::vector<T>(3);
}
int main() {
std::cout << Get<Data<int>>().data.size() << std::endl; // expected output is 2
std::cout << Get<std::vector<int>>().size() << std::endl; // expected output is 3
return 0;
}
Overloading won't help in this case, since call to Get<...>() will be ambiguious (see):
template <typename T>
Data<T> Get() {
return Data<T>{{T{}, T{}}};
}
template <typename T>
std::vector<T> Get() {
return std::vector<T>(3);
}
Any direction on how to overcome this are welcome.
There is workaround, that gives you something like this: do not specialize - overload:
#include <iostream>
#include <vector>
#include <string>
using namespace std;
template <typename T>
size_t Get(const T& data)
{
return 444;
}
template <typename T>
struct Data
{
std::vector<T> data;
};
template <typename T>
size_t Get(const Data<T>& data) {
return data.data.size();
}
int main() {
std::cout << Get<>(0) << std::endl; // expected output is 444
std::cout << Get<>(Data<int>{}) << std::endl; // expected output is 0
return 0;
}
Output:
444
0
Note, that size_t Get(const Data<T>& data) is not a specialization - it is completely "different" Get(), that is called for argument of type Data<T> for any T.
Here you can see working sample.
EDIT
I see you changed your question completely. However, I will still try to answer it. There is a standard workaround for lack of partial function specialization - using delegation to structs/classes.
Here is what you need:
#include <iostream>
#include <vector>
using namespace std;
template <typename T>
struct GetImpl;
template <typename T>
struct Data {
std::vector<T> data;
};
template <typename T>
struct GetImpl< Data<T> >
{
static Data<T> Get() {
return Data<T>{ {T{}, T{}} };
};
};
template <typename T>
struct GetImpl< std::vector<T> >
{
static std::vector<T> Get() {
return std::vector<T>(3);
};
};
int main() {
std::cout << GetImpl< Data<int> >::Get().data.size() << std::endl; // expected output is 2
std::cout << GetImpl< std::vector<int> >::Get().size() << std::endl; // expected output is 3
return 0;
}
Output:
2
3
Working sample can be found here.
If you don't like the syntax, you can make it a little bit shorter, by changing static function Get() to function call operator:
template <typename T>
struct Get< Data<T> >
{
Data<T> operator()() {
return Data<T>{ {T{}, T{}} };
};
};
template <typename T>
struct Get< std::vector<T> >
{
std::vector<T> operator()() {
return std::vector<T>(3);
};
};
And then:
Get< Data<int> >()().data.size();
Get< std::vector<int> >()().size();
You have only two extra characters - (). This is the shortest solution I can think of.
As Columbo mentioned in his comment, you should apply the standard workaround for lack of partial specialization support for functions: delegation to a partially specialized class:
template <typename T>
struct GetImpl;
template <typename T>
T Get() { return GetImpl<T>::Do(); }
and now use partial specialization on struct GetImpl<T> { static T Do(); } instead of Get<T>()
But it would be impossible for compiler to distinguish Get<Data<int>> from Get<Data<Data<int>>>.
It's not impossible. If that's something you need to do, we can add separate overloads:
template <typename T>
size_t Get(const Data<T>& data);
template <typename T>
size_t Get(const Data<Data<T>>& data); // preferred for Data<Data<int>>
Or if what you want is to only overload for the non-nested case, we can add a type trait and use SFINAE:
template <typename T> struct is_data : std::false_type { };
template <typename T> struct is_data<Data<T>> : std::true_type { };
template <typename T>
enable_if_t<!is_data<T>::value, size_t>
Get(const Data<T>& data);
That way, the call with Data<Data<int>> would call the generic Get(const T&). Or, if you want that case to not compile at all:
template <typename T>
size_t Get(const Data<T>& data) {
static_assert(!is_data<T>::value, "disallowed");
...
}
So overloading gives you lots of options. Specialization gives you none, since it's disallowed anyway.
Following delegation to the struct's way you can implement more general approach: you can use structs to check the container type and inner type like this:
#include <iostream>
#include <vector>
template <typename T>
struct Data {
std::vector<T> data;
};
template <template <typename...> class Container, typename>
struct get_inner;
template <template <typename...> class Container, typename T>
struct get_inner<Container, Container<T>>
{
typedef T type;
};
template <typename T, typename U = typename get_inner<Data, T>::type>
Data<U> Get() {
return Data<U>{ {U{}, U{}} };
}
template <typename T, typename U = typename get_inner<std::vector, T>::type>
std::vector<U> Get() {
return std::vector<U>(3);
}
int main() {
std::cout << Get<Data<int>>().data.size() << std::endl; // expected output is 2
std::cout << Get<std::vector<int>>().size() << std::endl; // expected output is 3
return 0;
}
http://coliru.stacked-crooked.com/a/90b55767911eff0e

how to implement is_pointer?

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.