Given a decorator class with standard decorator CTOR
explicit TheDecorator(std::unique_ptr<BaseClass> &&p_rrBase);
I want to create a member variable that is a unique ptr of such a decorator. I thus tried
unique_ptr<DerivedClass> spToDeco(make_unique<DerivedClass>() ); // class to decorate
m_spDecoration = make_unique<TheDecorator>( move(spToDeco) ); // unique ptr of decorator
Using VS 2010 and Scott Meyers implentation of make_unique (without variadic templates, implementing both a version with zero and one argument(s) instead), I get the error
error C2780: _Ty &&std::forward(...): expects 1 argument -- 0 provided
which I understand, as "TheDecorator" expects the argument to forward. But where the heck do I have to code it into, how do I form the syntax correctly? Am I supposed to include a move in the <> brackets? Thanks a lot for help!
Make_Unique:
namespace std
{
template<typename T>
std::unique_ptr<T> make_unique()
{
return std::unique_ptr<T>( new T() );
}
template<typename T, typename Ts>
std::unique_ptr<T> make_unique(Ts&& params)
{
return std::unique_ptr<T>( new T(std::forward<Ts>()) );
}
}
EDIT 2: SOLVED already, it must read
template<typename T, typename Ts>
std::unique_ptr<T> make_unique(Ts&& params)
{
return std::unique_ptr<T>( new T(std::forward<Ts>(params)) );
}
Related
In my class, I have a tuple object which I want to access the objects of in that as reference.
Actually, I want to know how can I write a get function to access the objects in my tuple?
I wrote a function which return the lvalue of my object in the tuple. I want to know how can I change it to return rvalue?
I have a template named GetIndex, which returns the index of type object in my tuple. In my tuple I definitely sure there are unique types object.
//return just lvalue
template <typename T>
T get_module()
{
return std::get<Private::GetIndex<T, Args...>::value>(types);
}
//compilation error
template <typename T>
T& get_module()
{
return &std::get<Private::GetIndex<T, Args...>::value>(types);
}
'''
You can just put & after T. It will be enough.
template <typename T>
T &get_module()
{
return std::get<Private::GetIndex<T, Args...>::value>(types);
}
I used template template parameter as follows:
/* [1]: Definition containing a template template parameter */
template <typename T, template<class> class Kernel>
void ForEach(Kernel<T> kernel, T * pSrc, int elementCount) {
//....
}
/* [2]: Definition of a helper struct */
template <typename T> struct KernelStd {
//...
};
/* [3]: Use the previous definitions */
float arr1[5] = {1,2,3,4,5};
//The following two calls to ForEach do successfully compile
ForEach(KernelStd<float>(), arr1, 5); //USE1
ForEach<float>(KernelStd<float>(), arr1, 5); //USE2
/* [4]: Definition of a helper function */
template <typename F, typename ...Args>
void forwarder(F func1, Args && ...args) {
//...
func1(std::forward<Args>(args)...);
}
//But the following callS do not compile.
forwarder(ForEach, KernelStd<float>(), arr1, 5); //USE3
forwarder(ForEach<float>, KernelStd<float>(), arr1, 5); //USE4
I am using VS2013 update 5 and I get the following error:
error C2783: 'void ForEach(Kernel<T>,T *,int)' : could not deduce
template argument for 'Kernel'
Any help will be appreciated.
forwarder is a function, so its first argument must be an entity (object or function) of type F.
ForEach is neither a function nor an object, it's a template. You therefore cannot pass ForEach to forwarder.
ForEach<float> does not pass enough template arguments to fully identify a function instantiated from the ForEach template. You can get away with it when calling the function template because of template argument deduction. But in the context of forwarder, the type F is supposed to be deduced from the first argument, so you have a bit of a chicken-and-egg problem.
If you want to use forwarder, you must supply it with an actual function, not with a template. So you'd have to do this:
forwarder(ForEach<float, KernelStd>, KernelStd<float>(), arr1, 5);
ForEach<float, KernelStd> contains all template arguments and it therefore designates a function (instantiated from a template).
(I had no idea how to name this question and I couldn't find anything similar. Sorry if this is duplicate)
If I want to inherit from some base template class, I can do this that way:
template<typename A=int, typename B=char> class C {};
template<typename... Args> class D : public C<Args...> {}; //it works!
This way I can change in project passed parameters to template class C and I don't have to change every usage of class D. Great. But what if I have template class using not only types as parameters but also values? For example:
template<int dim=3, typename float_t=double> class GeometricObject{};
template<typename... Args> class Point : public GeometricObject<Args...>{}; //it doesnt work
Of course I could define last template with integer type on the beginning. But this is not a way, if I would have 100 different classes all inheriting from GeometricObject and then I would change default dim value to 2, I would have to change every single class definition.
I also hope that there is the way without using any #define, #else and similar preprocessor commands. I know that templates are in fact also preprocessor commands, but... well, let's be modern here ;)
You can not mix type and non-type parameters in a template parameter pack. But it seems that your Point and other derived classes don't need to access the parameter pack arguments separately. In such cases it's easier, as well as more semantically correct, to pass the base class:
template<int dim=3, typename float_t=double> class GeometricObject{};
template<class GeometricObject=GeometricObject<>> class Point : public GeometricObject{};
Instantiating a Point could then look like:
Point<> a{}; // the same as Point<GeometricObject<>> a{};
Point<GeometricObject<4>> b{};
Point<GeometricObject<2, float>> c{};
Of course the GeometricObject<...> could be typedef'd to something shorter. Also, it can be made to look like a namespace instead of providing parameters to each geometric object separately:
template<int dim = 3, typename float_t = double>
struct GeometricObjects {
using Base = GeometricObject<dim, float_t>;
using Point = ::Point<Base>;
// ...
};
using TwoDim = GeometricObjects<2>;
TwoDim::Point a{};
I suppose you have multiple template classes and you want your Point object to be able to inherit from them all.
Instead of doing:
template <typename ... Args>
class Point : public GeometricObject<Args...>{};
I would instead do:
template <typename T>
class Point : public T {};
Now we just have to define proper traits to access the types template parameters in case they are needed. These types should be factored into a std::tuple (for instance).
The burden to fill this trait is on the GeometricObject class. For example, with your definition we would have:
template <typename T>
struct type_parameters;
template <int N, typename Float>
struct type_parameters<GeometricObject<N, Float> {
typedef std::tuple<Float> types;
};
The main scenario: a method of Point needs the type template parameters of GeometricObject (to forward them to a method of GeometricObject). To achieve this, you will have to pass in a tuple that will be unfold to call the inner method. To do so I make use of features added in the STL for C++14. You could still rewrite them yourself but I spared me the hassle for this question...
template <typename T>
class Point : public T {
template <typename Method, typename ... Args, std::size_t ... Is>
auto call_unfold(Method method, std::tuple<Args...> const& tuple, std::integer_sequence<std::size_t, Is...>) {
return (this->*method)(std::get<Is>(tuple)...);
}
template <typename Method, typename Tuple>
auto call_unfold(Method method, Tuple const& tuple) {
return call_unfold(method, tuple, std::make_index_sequence<std::tuple_size<Tuple>::value>());
}
public:
typedef typename type_parameters<T>::types types;
void some_method(types const& args) {
return call_unfold(&T::some_method, args);
}
};
This example is quite meaningless but the same technique could be useful with constructors of Point that need to call a base class constructor.
A live demo showing how it works is available on Coliru
Ok, so I figured it out how I should include variable-type template parameters into tuples. Basically I need to 'encapsulate' them into new parameter. This example works perfectly well AND solves my problem:
#include <type_traits>
template<int n = 2> struct Dim {
const int dim = n;
};
template<typename T> class SillyBaseClass {
public:
typedef typename T dim;
};
template<typename... Args> class SillyDerivedClass : public SillyBaseClass<Args...>{
public:
typedef typename SillyBaseClass::dim dim;
SillyDerivedClass() {
static_assert(std::is_same<dim,Dim<2>>::value,
"Number of dimensions must be equal to 2");
}
};
int main() {
SillyDerivedClass<Dim<2>> Class2d; //this works
SillyDerivedClass<Dim<3>> Class3d; //this returns expected error
}
In this test:
#include <string>
struct thing {
std::string name_;
};
class test {
thing id_;
public:
test(thing id) : id_{std::move(id)} {}
};
I would expect struct thing to have an implicit move constructor, so that class test can use std::move() to initialise its data member.
Clang version 3.4.1 gives this error:
error: no viable conversion from 'typename remove_reference<thing&>::type' (aka 'thing') to 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >')
The problem can be solved by adding a move constructor to struct thing, which of course means that a converting constructor and an explicitly defaulted copy constructor also needs to be added.
I do not understand why I cannot move struct thing around implicitly.
You are using a brace initialization - id_{std::move(id)}. In your case, as though struct thing is a POD (plain old data) it means, that C++ compiler tries to initialize the first member - std::string name_ instead of using a default constructor of struct thing object. Read more about aggregates and PODs.
In this case, because of the braces, class test's constructor is equivalent to something like this:
class test {
thing id_;
public:
test(thing id) {
id_.name_ = std::move(id); // Notice that this causes
// the "no viable conversion" error
}
};
Solution 1: You need to declare explicitly that you want to use a default struct thing's constructor by using parenthesis instead of braces:
#include <string>
struct thing {
std::string name_;
};
class test {
thing id_;
public:
test(thing id) : id_(std::move(id)) {} // Default c-tor will be used
};
Solution 2: You could also declare a user-defined constructor of struct thing to make it non-POD:
#include <string>
struct thing {
std::string name_;
thing(thing&&) {} // Used-defined move constructor
};
class test {
thing id_;
public:
test(thing id) : id_{std::move(id)} {} // You can use braces again
};
class baseFunctor{
virtual ~baseFunctor() {}
virtual bool operator()(const A& lhs, const A& rhs) = 0;
};
class derivedFunctor : public baseFunctor{
bool operator()(const A& lhs, const A& rhs) override { /*implementation*/ }
};
Inside another unrelated method, I have :
baseFunctor* functor = new derivedFunctor();
std::vector<A> vectorA;
My intention is to use this functor as a compare function like this:
std::make_heap(vectorA.begin(),vectorA.end(),*functor);
However, I get the following error:
C2893 Failed to specialize function template 'void
std::make_heap(_RanIt,_RanIt,_Pr)'
What is the proper way to use my pointer to functor in that situation?
Function objects are passed by value in standard algorithms. This means that the derivedFunctor object will be passed by value as a baseFunctor. Since baseFunctor is an abstract class that code cannot compile. (If it was not an abstract class the code would compile, but probably misbehave because of the object slicing problem.)
In order to make this work, you can use something like std::reference_wrapper:
std::make_heap(vectorA.begin(),vectorA.end(),std::ref(*functor));
This works because the reference wrapper object avoids copying the functor and keeps a reference instead; and because it is directly callable and simply forwards arguments to the object reference.