template method specialization inside template class - c++

I need (want) to specialize a method inside a template class, to allow only certain primitive types. (This is not a duplicate question of this)
Well i've got this class :
template<typename TYPE, size_t NB>
class X
{
public:
template<typename arg_type>
X& get(const arg_type var);
}
I would like to specialize arg_type to allow only unsigned integers, something like this :
template<typename TYPE, size_t NB> template<unsigned long> X& X::get(const unsigned long val);
But sure, the above doesn't work, neither on msvc2011 nor on gcc
To be more specific, what i try to do is to write a code based on the templated type above, and write the specialization so that anyone using this class X cannot use this method with something else than what i specialized.
Is that even possible ? and if it is, is it bad to do it so ?
Thanks in advance,
jav974

A specialization is not what you want. Using a specialization you can provide a special way to treat the instantiation of your template method using an unsigned integral type, but nothing prevents the user from instantiating it with another type.
You can achieve this using some SFINAE:
#include <type_traits>
template<typename TYPE, size_t NB>
class X
{
public:
template<typename arg_type>
typename std::enable_if<std::is_unsigned<arg_type>::value, X&>::type // arg_type is unsigned
get(arg_type val)
{
}
};
You could also use static_assert, so that users get a more friendly error message:
template<typename arg_type>
X& get(arg_type val)
{
static_assert(std::is_unsigned<arg_type>::value, "The argument should be unsigned!");
}
If you want the TYPE template parameter to follow the same rules, you could also use static_assert:
template<typename TYPE, size_t NB>
class X
{
public:
static_assert(std::is_unsigned<TYPE>::value, "TYPE should be unsigned!");
};

Related

Divorce a parameter pack in a class template

I am trying to write a class template that uses a parameter-pack and implements a member function for each type contained in the parameter-pack.
This is what I have so far:
template <typename...T>
class Myclass {
public:
void doSomething((Some_Operator_to_divorce?) T) {
/*
* Do Something
*/
std::cout << "I did something" << std::endl;
}
};
My goal is to have a class template that can be used in the following way:
Myclass<std::string, int, double> M;
M.doSomething("I am a String");
M.doSomething(1234);
M.doSomething(0.1234);
Where the class template mechanism will create an implementation for a doSomething(std::string x), a doSomething(int x) and a doSomething(double x) member function but not a doSomething(std::string x, int i, double f) member function.
I found a lot of examples in the web on the usability of parameter-packs, but I could not figure out if it can be used for my purpose, or if I totally misunderstood for what a parameter-pack can be used.
I thought that I need to unpack the parameter-pack but, after reading a lot of examples about unpacking parameter packs, I believe that this is not the right choice and it has a complete different meaning.
So, therefore, I am looking for a operation to "divorce" a parameter-pack.
There is no "operator" specifically that supports this, but what you're requesting can be done in a few different ways, depending on your requirements.
The only way to "extract" T types from a parameter pack of a class template with the purpose of implementing an overload-set of functions is to implement it using recursive inheritance, where each instance extracts one "T" type and implements the function, passing the rest on to the next implementation.
Something like:
// Extract first 'T', pass on 'Rest' to next type
template <typename T, typename...Rest>
class MyClassImpl : public MyClassImpl<Rest...>
{
public:
void doSomething(const T&) { ... }
using MyClassImpl<Rest...>::doSomething;
};
template <typename T>
class MyClassImpl<T> // end-case, no more 'Rest'
{
public:
void doSomething(const T&) { ... }
};
template <typename...Types>
class MyClass : public MyClassImpl<Types...>
{
public:
using MyClassImpl<Types...>::doSomething;
...
};
This will instantiate sizeof...(Types) class templates, where each one defines an overload for each T type.
This ensures that you get overload semantics -- such that passing an int can call a long overload, or will be ambiguous if there are two competing conversions.
However, if this is not necessary, then it'd be easier to enable the function with SFINAE using enable_if and a condition.
For exact comparisons, you could create an is_one_of trait that only ensures this exists if T is exactly one of the types. In C++17, this could be done with std::disjunction and std::is_same:
#include <type_traits>
// A trait to check that T is one of 'Types...'
template <typename T, typename...Types>
struct is_one_of : std::disjunction<std::is_same<T,Types>...>{};
Alternatively, you may want this to only work if it may work with convertible types -- which you might do something like:
template <typename T, typename...Types>
struct is_convertible_to_one_of : std::disjunction<std::is_convertible<T,Types>...>{};
The difference between the two is that if you passed a string literal to a MyClass<std::string>, it will work with the second option since it's convertible, but not the first option since it's exact. The deduced T type from the template will also be different, with the former being exactly one of Types..., and the latter being convertible (again, T may be const char*, but Types... may only contain std::string)
To work this together into your MyClass template, you just need to enable the condition with SFINAE using enable_if:
template <typename...Types>
class MyClass
{
public:
// only instantiates if 'T' is exactly one of 'Types...'
template <typename T, typename = std::enable_if_t<is_one_of<T, Types...>::value>>
void doSomething(const T&) { ... }
// or
// only instantiate if T is convertible to one of 'Types...'
template <typename T, typename = std::enable_if_t<is_convertible_to_one_of<T, Types...>::value>>
void doSomething(const T&) { ... }
};
Which solution works for you depends entirely on your requirements (overload semantics, exact calling convension, or conversion calling convension)
Edit: if you really wanted to get complex, you can also merge the two approaches... Make a type trait to determine what type would be called from an overload, and use this to construct a function template of a specific underlying type.
This is similar to how variant needs to be implemented, since it has a U constructor that considers all types as an overload set:
// create an overload set of all functions, and return a unique index for
// each return type
template <std::size_t I, typename...Types>
struct overload_set_impl;
template <std::size_t I, typename T0, typename...Types>
struct overload_set_impl<I,T0,Types...>
: overload_set_impl<I+1,Types...>
{
using overload_set_impl<I+1,Types...>::operator();
std::integral_constant<std::size_t,I> operator()(T0);
};
template <typename...Types>
struct overload_set : overload_set_impl<0,Types...> {};
// get the index that would be returned from invoking all overloads with a T
template <typename T, typename...Types>
struct index_of_overload : decltype(std::declval<overload_set<Types...>>()(std::declval<T>())){};
// Get the element from the above test
template <typename T, typename...Types>
struct constructible_overload
: std::tuple_element<index_of_overload<T, Types...>::value, std::tuple<Types...>>{};
template <typename T, typename...Types>
using constructible_overload_t
= typename constructible_overload<T, Types...>::type;
And then use this with the second approach of having a function template:
template <typename...Types>
class MyClass {
public:
// still accept any type that is convertible
template <typename T, typename = std::enable_if_t<is_convertible_to_one_of<T, Types...>::value>>
void doSomething(const T& v)
{
// converts to the specific overloaded type, and call it
using type = constructible_overload_t<T, Types...>;
doSomethingImpl<type>(v);
}
private:
template <typename T>
void doSomethingImpl(const T&) { ... }
This last approach does it two-phase; it uses the first SFINAE condition to ensure it can be converted, and then determines the appropriate type to treat it as and delegates it to the real (private) implementation.
This is much more complex, but can achieve the overload-like semantics without actually requiring recursive implementation in the type creating it.

How to decltype template method C++?

I write interfaces through concepts for implementation validation.
There are no problems with conventional methods:
// Interface realization
struct Realization
{
int* TestMethod(const std::string& aStr)
{
return (int *) aStr.c_str();
}
};
// Concept
template <typename T>
concept IRealization = std::is_same_v<decltype(&T::TestMethod), int* (T::*)(const std::string&)>;
// and then, for example
void Check()
{
static_assert(IRealization<Realization>)
}
but when I try to write a similar check for a template method:
// Interface realization
struct Realization
{
template <typename T>
int* TemplateMethod(const T& aStr)
{
return (int *) aStr.c_str();
}
};
, I run into a problem of dectype a template method, because I cant write
decltype(&RealizationImpl::TemplateMethod)
(at the time of checking the interface, I do not know the type that will be substituted)
Please tell me, can I somehow get the signature of the template function without type, or otherwise solve my problem? Thanks!
You should not write concepts like this. A concept should never check for something as specific as a member function with an exact signature. A concept should instead say that, given an instance of the type in question, I should be able to do i.memberFunc(...), where ... is the list of parameters.
For example, your "IRealization" concept (please don't prefix concepts with I. Concepts are not interfaces) ought to say "T must have a member function which can be called given a std::string argument and results in something which is convertible to an int." That would look like:
template <typename T>
concept IRealization = requires(T t, std::string str)
{
{ t.TestMethod(str) } -> convertible_to<int>;
};
This allows the user to provide a TestMethod that takes, for example, std::string_view instead of std::string. There's no point in being so incredibly restrictive on the type.
A concept that checks for T having a member function which is callable with some type U would have to be templated on both T and U:
template <typename T, typename U>
concept IRealization = requires(T t, U u)
{
{ t.TestMethod(u) } -> convertible_to<int>;
};
What is the problem with adding another type to the concept?
// Concept
template <typename T, typename U>
concept IRealization = std::is_same_v<decltype(&T::template TestMethod<U>), int* (T::*)(const U&)>;
For instance.
You could even make it prettier by creating a typedef -
template<typename T, typename U>
using FuncT = decltype(&T::template TestMethod<U>);

Determine if there is an overloaded function defined for a parameter of a specific type

I have a simple serialization framework that defines specializations of Read and Write template functions for various types including arithmetic, my classes, and std containers like vector, array, map, etc..., so it is possible to do
std::vector<std::string> v{ "a1", "b123", "c12345" };
Read(stream, v);
Write(stream, v);
or
std::map<int, MyClass> m;
Read(stream, m);
Write(stream, m);
, for example.
I am looking for a way to determine at compile time is a type serializable or not by implementing something like this:
template <class T>
constexpr bool is_serializable()
{
if (Read<T> and Write<T> are defined)
return true;
return false;
}
or probably something else.
Is it possible?
The declarations of Read and Write:
template <typename T>
void Read(InputStream & s, T & val);
template <typename T>
void Write(OutputStream & s, T val);
theoretically I can define is_serializable for every type I need in addition to Read and Write, but this requires more typing and makes the code more complicated probably, so having is_serializable defined automatically is more elegant way.
It also can be some Serializer template class with Read and Write functions as members. In this case I need to know if there is a specialization of Serializer for a specific type. For example, I can do something like this with it.
You can use std::void_t and SFINAE to achieve that. The documentation of std::void_t in cppreference is great.
#include <type_traits>
#include <iostream>
void Read(std::istream &,double &) {}
void Write(std::ostream &,double) {}
template <typename T,typename= void>
struct is_serializable_t: std::false_type {};
template <typename T>
struct is_serializable_t<T,std::void_t<
decltype(Read(std::declval<std::istream &>(),std::declval<T &>())),
decltype(Write(std::declval<std::ostream &>(),std::declval<T>()))>>:
std::true_type {};
template <typename T>
inline constexpr bool is_serializable = is_serializable_t<T>::value;
static_assert(is_serializable<double>);
static_assert(!is_serializable<int>);

Specializing single method in a big template class

In C++ if you want to partially specialize a single method in a template class you have to specialize the whole class (as stated for example in Template specialization of a single method from templated class with multiple template parameters)
This however becomes tiresome in bigger template classes with multiple template parameters, when each of them influences a single function. With N parameters you need to specialize the class 2^N times!
However, with the C++11 I think there might a more elegant solution, but I am not sure how to approach it. Perhaps somehow with enable_if? Any ideas?
In addition to the inheritance-based solution proposed by Torsten, you could use std::enable_if and default function template parameters to enable/disable certain specializations of the function.
For example:
template<typename T>
struct comparer
{
template<typename U = T ,
typename std::enable_if<std::is_floating_point<U>::value>::type* = nullptr>
bool operator()( U lhs , U rhs )
{
return /* floating-point precision aware comparison */;
}
template<typename U = T ,
typename std::enable_if<!std::is_floating_point<U>::value>::type* = nullptr>
bool operator()( U lhs , U rhs )
{
return lhs == rhs;
}
};
We take advantage of SFINAE to disable/enable the different "specializations" of the function depending on the template parameter. Because SFINAE can only depend on function parameters, not class parameters, we need an optional template parameter for the function, which takes the parameter of the class.
I prefer this solution over the inheritance based because:
It requires less typing. Less typing probably leads to less errors.
All specializations are written inside the class. This way to write the specializations holds all of the specializations inside the original class , and make the specializations look like function overloads, instead of tricky template based code.
But with compilers which have not implemented optional function template parameters (Like MSVC in VS2012) this solution does not work, and you should use the inheritance-based solution.
EDIT: You could ride over the non-implemented-default-function-template-parameters wrapping the template function with other function which delegates the work:
template<typename T>
struct foo
{
private:
template<typename U>
void f()
{
...
}
public:
void g()
{
f<T>();
}
};
Of course the compiler can easily inline g() throwing away the wrapping call, so there is no performance hit on this alternative.
One solution would be to forward from the function, you want to overload to some implementation that depends on the classes template arguments:
template < typename T >
struct foo {
void f();
};
template < typename T >
struct f_impl {
static void impl()
{
// default implementation
}
};
template <>
struct f_impl<int> {
static void impl()
{
// special int implementation
}
};
template < typename T >
void foo< T >::f()
{
f_impl< T >::impl();
}
Or just use private functions, call them with the template parameter and overload them.
template < typename T >
class foo {
public:
void f()
{
impl(T());
}
private:
template < typename G >
void impl( const G& );
void impl( int );
};
Or if it's really just one special situation with a very special type, just query for that type in the implementation.
With enable_if:
#include <iostream>
#include <type_traits>
template <typename T>
class A {
private:
template <typename U>
static typename std::enable_if<std::is_same<U, char>::value, char>::type
g() {
std::cout << "char\n";
return char();
}
template <typename U>
static typename std::enable_if<std::is_same<U, int>::value, int>::type
g() {
std::cout << "int\n";
return int();
}
public:
static T f() { return g<T>(); }
};
int main(void)
{
A<char>::f();
A<int>::f();
// error: no matching function for call to ‘A<double>::g()’
// A<double>::f();
return 0;
}
Tag dispatching is often the clean way to do this.
In your base method, use a traits class to determine what sub version of the method you want to call. This generates a type (called a tag) that describes the result of the decision.
Then perfect forward to that implememtation sub version passing an instance of the tag type. Overload resolution kicks in, and only the implememtation you want gets instantiated and called.
Overload resolution based on a parameter type is a much less insane way of handling the dispatch, as enable_if is fragile, complex at point of use, gets really complex if you have 3+ overloads, and there are strange corner cases that can surprise you with wonderful compilation errors.
Maybe i'm wrong but chosen best anwser provided by Manu343726 has an error and won't compile. Both operator overloads have the same signature. Consider best anwser in question std::enable_if : parameter vs template parameter
P.S. i would put a comment, but not enough reputation, sorry

Getting type from template value, C++

I have the following method in which I'm using boost::variant. I try to get the value, based on type T. If boost::get<T> fails I want to handle that in a special way if T is an int or unsigned int. Is there any way to know if T is an int or unsigned int?
I don't think I can use template specialization in this case, can I?
EDIT: Also, I don't yet have access to C++11 (soon I hope)
template < typename T, typename C, void (C::*setterFcn)(const T&) >
void binder( const Variant& value_var, C* c )
{
const T* typeData = boost::get<T>(&value_var);
if ( NULL == typeData )
{
// Need to check for int or unsigned int here somehow
}
(((C*) c)->*(setterFcn))(*typeData);
}
In C++11 you can use std::is_same and in C++03 you can do something like this:
template <typename T1, typename T2>
class is_same
{
public:
static bool const value = false;
};
template <typename T>
class is_same<T, T>
{
public:
static bool const value = true;
};
and use it exactly as C++11 standard version.
You could also use is_same() on boost or on C++11.
http://www.boost.org/doc/libs/1_51_0/libs/type_traits/doc/html/boost_typetraits/reference/is_same.html
http://en.cppreference.com/w/cpp/types/is_same
The easiest way is probably to just delegate to overloaded functions or function templates: You specify the general handling, possibly doing nothing, in one function and the specialized handling either in two separate functions (if the extra handling is trivial) or in an enable_ifed function with the condition checking for int or unsigned int.