C++ template programming - Deferred function calls - c++

I am looking for an elegant solution to the following problem. I have a task struct that I use for deferred function calls.
template <typename T> struct Task1
{
T Arg1;
Delegate<T> TaskDelegate;
};
The problem I'm having is this:
Task1<const Foo&> MyTask;
This will result in the parameter being held as a const reference. Does anyone know a nice solution to get round this? I could enforce rules such as the delegate signature always taking const& params but this seems restrictive. I could always have two task structs (one for ref and one for value) but this seems nasty.
The other solution would be to create the following:
template <typename T1, typename T2> struct Task1
{
T2 Arg1;
Delegate<T1> TaskDelegate;
};
Is there anyway to default T2 to be the same type as T1? That way whenever I have a method value signature I don't need to have the additional template params.
EDIT:
The template is used for a multithreaded task scheduler. Here is an example:
void MyClass::Populate(const std::string& instrText);
CTaskScheduler::Schedule(Task1<const std::string&>(this, &MyClass::Popluate, "MyString"));

You could take a look at the implementation of function<> either in boost or the upcoming standard. As a matter of fact, you can just use function<>. I think that the solution there was (before C++0x) to always store a copy of the arguments, if the user wants reference semantics they can use a reference wrapper.
As to how to get to a value, you can take a look at some simple metafunction to remove const or &:
// Remove reference:
template <typename T>
struct remove_reference {
typedef T type;
};
template <typename T>
struct remove_reference<T&> {
typedef T type;
};
Similarly for const.

You can use the boost.type_traits library to remove the const-ness of the parameter using boost::remove_const.

In addition to boost::type_traits, there is a boos::call_traits library specifically built to handle problems like this. It also provides mechanisms to avoid the references of references problem.

boost::remove_const should help you in this case:
template <typename T> struct Task1
{
typename boost::remove_const<T>::type Arg1;
Delegate<T> TaskDelegate;
};
Alternatively, you can avoid using boost if you use template specialization for const types:
template <typename T> struct Task1
{
T Arg1;
Delegate<T> TaskDelegate;
};
template <typename T> struct Task1<const T>
{
T Arg1;
Delegate<const T> TaskDelegate;
};
(Warning: untested)

Related

How to overload template class by type- and non-type template parameters?

Is it possible to implement a template class Type which supports the following instantiations?
Type<int> typeArg_;
Type<nullptr> nonTypeArg_;
I hope there is a solution (especially without macro). Maybe std::enable_if-magic or something will help...
No, you can't do that.
The nature of a template parameter is fixed. It is either a type or non-type (value). It can't be a type for one use case and a non-type for another use case.
There might be ways to accomplish your goal if you can elaborate what that is.
As far I now, isn't possible in C++.
The best that come in my mind is to wrap values in types; something as
template <typename T, T Value>
struct ValueWrapper
{ };
and specialize Type for ValueWrapper
Something as
template <typename T>
struct Type
{ /* something with T */ };
template <typename T, T Value>
struct Type<ValueWrapper<T, Value>>
{ /* something with value */ };
The use become
Type<int> typeArg;
Type<ValueWrapper<std::nullptr_t, nullptr>> nonTypeArg;
or also
Type<ValueWrapper<decltype(nullptr), nullptr>> nonTypeArg;
As pointed by Jarod42 (thanks) the standard (starting from C++11) provides a standard structure that make the ValueWrapper function: std::integral_constant.
You can use it instead of ValueWrapper but doesn't works, for std::integral_constant, the following C++17 semplification.
Because if you can use C++17, all become simpler: you can use auto for value types, so ValueWrapper become
template <auto Value>
struct ValueWrapper
{ };
so Type non-type specialization become
template <auto Value>
struct Type<ValueWrapper<Value>>
{ /* something with value */ };
and the use
Type<int> typeArg;
Type<ValueWrapper<nullptr>> nonTypeArg;

template<typename> - how does it work?

I have come across such syntax:
template<typename>
struct is_const{static const bool value = 0;};
How will this code behave and how could it be applied? I didn't find any example or explanation in the Internet.
I am wondering about lack of the argument name (e.g. T).
This is a primary template which takes a single template argument and has a static bool member equal to 0. It is likely that this is the primary template definition for a type trait and that there is a corresponding specialization elsewhere which looks like this:
template <typename T>
struct is_const<const T>
{static const bool value = 1;};
This would allow you to check if a type is const qualified like so:
static_assert(!is_const<int>::value, "wat");
static_assert(is_const<const int>::value, "wat");
template <typename T>
class SampleClass
{
public:
T values [2];
SampleClass(T first, T second)
{
values[0]=first;
values[1]=second;
}
};
Try Something like this typename are generic way of programming. search for generic programming c++. You will get alot of resources
On a basic level of explanation, each time the template is used the compiler generates a version of the templated struct, class, function, etc.
for example:
template<typename T>
struct StructName
{
T memberVariable;
};
when this code is used:
StructName<float> variable = StructName<float>();
the compiler generates:
struct StructName
{
float memberVariable;
};
you can read more about this here: https://en.wikipedia.org/wiki/Template_metaprogramming

How can I get the C++ compiler to deduce T indirectly?

My template-fu is rather weak. I have this code:
template<typename T>
void Foo(void(*func)(T*)) { }
void Callback(int* data) { }
int Test()
{
Foo(Callback);
}
...but I'd like something more readable than C's nasty function pointer syntax of void(*func)(T*).
Someone on my team suggested this:
template<typename T>
struct Types
{
typedef void Func(T*);
};
template<typename T>
void Foo2(typename Types<T>::Func* func) {}
void Test2()
{
Foo2(Callback); // could not deduce template argument for 'T'
Foo2<int>(Callback); // ok
}
(I'm still debating whether this is actually more readable, but that's a separate issue.)
How can I help the compiler figure out what T is without needing to explicitly specify it in the caller?
You can extract T from the function type using a traits class.
template<class F>
struct CallbackTraits;
template<class T>
struct CallbackTraits<void(*)(T)>
{
typedef T ArgumentType;
};
Your example can be modified like this:
template<typename F>
void Foo(F func)
{
typedef typename CallbackTraits<F>::ArgumentType T;
}
void Callback(int* data) { }
int Test()
{
Foo(Callback);
}
This technique is used in the boost type-traits library:
http://www.boost.org/doc/libs/1_57_0/libs/type_traits/doc/html/boost_typetraits/reference/function_traits.html
This blog post goes into a bit more detail about the implementation of the technique:
https://functionalcpp.wordpress.com/2013/08/05/function-traits/
Unfortunately this approach hides the information in the signature of Foo about the constraints on the argument passed in. In the above example the argument must be a function of type void(T*).
This alternative syntax does the same as the original example while being slightly more readable:
template<typename T>
void Foo(void func(T*)) { }
Another alternative syntax that may be more readable can be achieved using c++11's alias templates as follows:
template<typename T>
using Identity = T;
template<typename T>
void Foo(Identity<void(T*)> func) { }
Unforunately the latest MSVC fails to compile this, reporting an internal compiler error.
You won't be able to deduce the type based on a nested name: there is no reason why different instantiations of the outer type won't define an identical inner type. You could use a using alias, though:
template <typename T>
using Function = auto (*)(T*) -> void;
template <typename T>
void Foo(Function<T>) {
}
Personally, I would recommend against using any of that, however: in practice it seems much more advisable to actually take a function object which later allows using object with suitable function call operators to be used. For callbacks it is quite common that you'll need to pass in some auxiliary data. That is, you would either use an unconstrained template or one which takes a type-erased type, depending on what you want to do exactly:
template <typename Fun>
void Unconstrained(Fun fun) {
}
template <typename T>
void TypeErased(std::function<void(T*)> fun) {
}
The unconstrained version has the advantage that it can potentially inline the function call but it has the disadvantage that every function object type creates a new instantiation and that the argument types are likely to vary. The type-erased version effectively has to do something like a virtual function call but there is just one instantiation of the function template (per argument type T, of course).
Admittedly, the type-erased version's type won't be deduced from a function pointer (or any other argument which isn't a std::function<void(X*)>), i.e., you may want to have a forwarding function
template <typename T>
void TypeErased(Function<T> fun) {
TypeErased(std::function<void(T)>(fun));
}
In C++98 and C++03 template argument deduction only works with functions (and methods).
I don't think the picture changed in the more recent standards.

Changing deleter for std::unique_ptr

I want to change default_deleter for std::unique_ptr. This is quite easy to achieve, but there is one inconvenient - I have to declare variables using 2 template parameters instead of one, something like this:
std::unique_ptr<MyType, MyDeleter<MyType>> myVar;
As you may see the declaration is long and I have a feeling I can use a shorter version, but I don't know how:)
Is it possible to declare some kind of MyUniquePtr<T> that will be the same as std::unique_ptr<T, MyDeleter<T>>?
EDIT: Matthieu M. already answered, but unfortunately I can't use this feature in Visual Studio as it's not implemented. Is there other way to have this behavior?
Actually it is, using template aliases:
template <typename T>
using MyUniquePtr = std::unique_ptr<T, MyDeleter<T>>;
If your compiler doesn't do template aliases yet, here's the C++03 idiom:
template <typename T>
struct MyUniquePtr {
typedef std::unique_ptr<T, MyDeleter<T> > type;
};
MyUniquePtr<MyType>::type var;
The setup is uglier, but the resulting usage is almost as short: you just need to add ::type.
Does your deleter need to be templated on the type of the object being deleted, or is it sufficient for the function call operator to be templated on the type of object being deleted?
Instead of:
template<typename T>
struct MyDeleter
{
void operator()(T* p) const { /* ... */ }
};
Can you write:
struct MyDeleter
{
template<typename T>
void operator()(T* p) const { /* ... */ }
};
This, of course, depends on what state MyDeleter has to maintain.
Another way conforming to c++03 is a subclass, which unfortunately requires you to reproduce the constructors. (This can be done easier, if your compiler supports variadic template arguments, which may be the case for current MSVC.)
template <class T>
class MyUniquePtr : public std::unique_ptr< T, MyDeleter<T> > {
public:
MyUniquePtr(args...) : std::unique_ptr< T, MyDeleter<T> >(args...) { }
};
You might want to consider writing your own version of a make_unique style function instead specialized for your custom allocation / deletion strategy. This also has the advantage that you can perform any specialized resource acquisition / allocation in an exception safe way. You can then declare your unique_ptr as auto and let type deduction work for you.

Knowing the number of template parameters in the declaration

If I have,
template<typename T1, typename T2, int N>
class X {};
Is there any way, that I can know class X has 3 template arguments ?
Use case in brief: There are two library classes ptr<T> (for normal pointer) and ptr_arr<T,N> (for pointer to array). These two are interacting with another class in following way:
template<typename T>
void Clear(const T &obj)
{
if(T::Args == 1) destroy(obj);
else destroy_arr(obj);
}
So, I thought if we have some handy way of knowing the number of parameters, it would make it easy. However, I learn that I need to change my business logic as there cannot be such way.
There is no standard way to do this (unless you use variadic sizeof(Args...) in C++0x) but that's beside the point -- the question is wrong.
Use overload resolution.
template <typename T>
void clear (ptr<T> & obj) {
destroy (obj);
}
template <typename T, int N>
void clear (ptr_arr<T,N> & obj) {
destroy_arr (obj);
}
You can use the mpl::template_arity (undocumented)
http://www.boost.org/doc/libs/1_40_0/boost/mpl/aux_/template_arity.hpp
There is no way to do this. Imagine the amount of overloads.
template<int> struct A;
template<bool> struct B;
template<char> struct C;
template<typename> struct D;
template<D<int>*> struct E;
template<D<bool>*> struct F;
template<typename, int> struct G;
// ...
For each of that, you would need a different template to accept them. You cannot even use C++0x's variadic templates, because template parameter packs only work on one parameter form and type (for example, int... only works for a parameter pack full of integers).