How to set a function as a default parameter? - c++11

I ran into a problem with setting a function as a default parameter.
The following code doesn't make a lot of sense. What I want to achieve can be done in many different ways. This code only describes the problem I ran into and wish to know how to fix it to work to my specifications.
#include <iostream>
#include <vector>
int double_the_number(int x)
{
return x * 2;
}
template<typename T, typename FunctionType>
std::vector<FunctionType> copy_with_criteria(T iter1, T iter2, FunctionType F(FunctionType))
{
std::vector<int> new_vector;
while(iter1 != iter2)
{
new_vector.push_back(F(*iter1++));
}
return new_vector;
}
int main()
{
std::vector<int> v {1,2,3,4,5};
auto new_vector = copy_with_criteria(v.begin(), v.end(), double_the_number);
for(int x : new_vector) std::cout << x << " ";
return 0;
}
When the code above is ran, it will output 2 4 6 8 10
What I want to achieve is if I call a function without specifying the criteria function copy_with_criteria(v.begin(), v.end()) I want it to output 1,2,3,4,5
That is, somehow I would like to set the function as a default parameter which is a type of elements inside some container (in this case vector) and which returns number that has been sent to it, like this (TypeOfElements is just an example of what type the default criteria function should be):
TypeOfElements default_function(TypeOfElements x) {
return x;
}
I would not like to use any external libraries. Also I am working with c++11.
If anyone could help me with this problem I would be very grateful!
Thank you :)

Overload your function.
template <typename T>
std::vector<typename std::iterator_traits<T>::value_type>
copy_with_criteria(T iter1, T iter2)
{
return std::vector<typename std::iterator_traits<T>::value_type>(iter1, iter2);
}

You can define your function as:
template<typename T, typename FunctionType = typename std::decay<decltype(*std::declval<T>())>::type>
std::vector<FunctionType> copy_with_criteria(T iter1, T iter2, FunctionType(*F)(FunctionType) = [](FunctionType v){ return v; }) {
// ...
}
It works in C++11 as requested (see it on Coliru).
The basic idea is that you can deduce FunctionType directly from the type of the iterators and not from the function F. Then you can give to F a default by using a lambda function that is nothing more than an identity function.
Otherwise you can simply overload copy_with_criteria as suggested by aschepler (I'd rather go with his approach instead of using a default argument) or simply define a different function with a meaningful name that is explicit about your intention for you are not using criteria during that kind of copy.
Edit
As suggested by #aschepler in the comments, you can use iterator_traits<T>::value_type instead of typename std::decay<decltype(*std::declval<T>())>::type to avoid problems with some types.

Functions are the wrong thing to use here. State can easily be useful. You want to use a generic function object. And deduce the return value.
In addition, using iterator ranges is questionable. The next iteration of C++ range library is going to reduce that use.
While you want a C++11 solution, there is no reason to use the C++03/C++11 style. Be forward looking.
So let us get started.
#include <iterator>
namespace notstd {
namespace adl_helper {
using std::begin; using std::end;
template<class C>
auto adl_begin( C&& )
-> decltype( begin( std::declval<C>() ) );
template<class T, std::size_t N>
auto adl_begin( T(*)[N] )
-> T*;
}
template<class C>
using iterator_type=decltype(
::notstd::adl_helper::adl_begin( std::declval<C>() )
);
}
This finds the iterator type of a container via calling std::begin in an ADL-enabled context. This emulates what a for(:) loop does reasonably well.
namespace notstd {
template<class C>
using value_type = typename std::iterator_traits<
iterator_type<C>
>::value_type;
}
now we can value_type<C> for some type C and get the type it contains.
namespace notstd {
struct make_a_copy_t {
template<class T>
auto operator()(T&& t)const
-> std::decay_t<T>
{
return std::forward<T>(t);
}
};
}
make_a_copy_t is a functor that copies stuff.
We are almost ready to solve your problem.
template<class Op=notstd::make_a_copy_t, class C,
class R=decltype( std::declval<Op&>()(std::declval<notstd::value_type<C&>>()) )
>
std::vector<R>
copy_with_criteria(C&& c, Op op={})
{
std::vector<R> new_vector;
for (auto&& e:std::forward<C>(c))
{
new_vector.push_back( op(decltype(e)(e)) );
}
return new_vector;
}
and I believe this satisfies your criteria.
You may also need
namespace notstd {
template<class It>
struct range_t {
It b = {};
It e = {};
It begin() const { return b; }
It end() const { return e; }
range_t( It s, It f ):b(std::move(s)), e(std::move(f)) {}
range_t( It s, std::size_t count ):
range_t( s, std::next(s, count) )
{}
range_t() = default;
range_t(range_t&&)=default;
range_t(range_t const&)=default;
range_t& operator=(range_t&&)=default;
range_t& operator=(range_t const&)=default;
range_t without_front(std::size_t N)const {
return {std::next(begin(), N), end()};
}
range_t without_back(std::size_t N)const {
return {begin(), std::prev(end(),N)};
}
std::size_t size() const {
return std::distance(begin(), end());
}
// etc
};
template<class It>
range_t<It> range( It b, It e ) {
return {std::move(b), std::move(e)};
}
template<class It>
range_t<It> range( It b, std::size_t count ) {
return {std::move(b), count};
}
template<class C>
range_t<iterator_type<C&>> range( C& c ) {
using std::begin; using std::end;
return {begin(c), end(c)};
}
}
which lets you do operations on subsections of a container as a range.
So suppose you want to take the first half of a vector of int and double it.
std::vector<int> some_values{1,2,3,4,5,6,7,8,9,10};
auto front_half = notstd::range(some_values).without_back(some_values.size()/2);
auto front_doubled = copy_with_criteria( front_half, [](int x){return x*2;} );
and done.
Live example.

Related

Cannot iterate on a non-copyable container returned by a function

I'm not sure of the title, because I'm not sure the issue comes from the "copyablility" of my container.
I tryied quite everything but I can't get rid of this error.
Here is a simplified version of my code (please do not challenge the class design, I really would like to keep the end-used syntax in the BOOST_FOREACH):
template <typename T>
class MyContainer
{
public:
typedef typename std::vector<T>::iterator iterator;
typedef typename std::vector<T>::const_iterator const_iterator;
MyContainer(std::vector<T>& vec, boost::mutex& mutex) :
m_vector(vec),
m_lock(mutex)
{
}
iterator begin() { return m_vector.begin(); }
const_iterator begin() const { return m_vector.begin(); }
iterator end() { return m_vector.end(); }
const_iterator end() const { return m_vector.end(); }
private:
std::vector<T>& m_vector;
boost::lock_guard<boost::mutex> m_lock;
};
template <typename T>
struct GetContainer
{
GetContainer(std::vector<T>& vec, boost::mutex& mutex) :
m_vector(vec),
m_mutex(mutex)
{
}
MyContainer<T> Get()
{
return MyContainer<T>(m_vector, m_mutex);
}
std::vector<T>& m_vector;
boost::mutex& m_mutex;
};
int main()
{
std::vector<int> v;
v.push_back(1);
v.push_back(2);
boost::mutex m;
GetContainer<int> getter(v, m);
BOOST_FOREACH(int i, getter.Get())
{
std::cout << i << std::endl;
}
return 0;
}
The compiler complains about not having a copy constructor for MyContainer::MyContainer(const MyContainer&).
I also have :
error: no matching function for call to ‘MyContainer::MyContainer(boost::foreach_detail_::rvalue_probe >::value_type)’
I follow the extensibility tips:
http://www.boost.org/doc/libs/1_58_0/doc/html/foreach/extensibility.html#foreach.extensibility.making__literal_boost_foreach__literal__work_with_non_copyable_sequence_types
But, making
MyContainer<T> : private boost::noncopyable
doesn't solve the issue.
Nor defining the function
boost_foreach_is_noncopyable
or specializing the template struct
is_noncopyable
for MyContainer (in fact, how would I specialize this template for a template type ?)
Last "tip":
If I remove the mutex and the lock from everywhere (I just pass the vector to GetContainer and to MyContainer), it works.
But it doesn't work if I make
MyContainer<T> : private boost::noncopyable
(I expected it should, so I'm not sure my problem is with BOOST_FOREACH, but maybe because I return a copy of MyContainer with my getter ?)
I thank you if you read me until here, and thanks in advance for help.
Seems to be a limitation of BOOST_FOREACH with move-only types. I didn't find a way around it¹ (except for the - ugly - obvious approach to put the lock_guard in a shared_ptr).
You didn't specify a c++03 requirement, though, so you can make it work without BOOST_FOREACH by replacing lock_guard with unique_lock.
Here's my take on things in c++11 (note how generic it is):
Live On Coliru
#include <boost/thread.hpp>
#include <boost/range.hpp>
namespace detail {
template <typename R, typename M>
struct RangeLock {
RangeLock(R&r, M& m) : _r(r), _l(m) {}
RangeLock(RangeLock&&) = default;
using iterator = typename boost::range_iterator<R>::type;
iterator begin() { using std::begin; return begin(_r); }
iterator end () { using std::end; return end (_r); }
using const_iterator = typename boost::range_iterator<R const>::type;
const_iterator begin() const { using std::begin; return begin(_r); }
const_iterator end () const { using std::end; return end (_r); }
private:
R& _r;
boost::unique_lock<M> _l;
};
}
template <typename R, typename M>
detail::RangeLock<R,M> make_range_lock(R& r, M& mx) { return {r,mx}; }
template <typename R, typename M>
detail::RangeLock<R const,M> make_range_lock(R const& r, M& mx) { return {r,mx}; }
#include <vector>
#include <map>
int main() {
boost::mutex mx;
std::vector<int> const vec { 1, 2 };
std::map<int, std::string> const map { { 1, "one" }, { 2, "two" } };
for(int i : make_range_lock(vec, mx))
std::cout << i << std::endl;
for(auto& p : make_range_lock(map, mx))
std::cout << p.second << std::endl;
for(auto& p : make_range_lock(boost::make_iterator_range(map.equal_range(1)), mx))
std::cout << p.second << std::endl;
}
Prints
1
2
one
two
one
¹ not even using all the approaches from Using BOOST_FOREACH with a constant intrusive list
I post my answer if it can help...
With C++03, I finally provide a copy constructor to be able to use the class with BOOST_FOREACH.
So the issue is moved to another topic: make the class copied in a logic and suitable way.
In my case, I "share the lock and the vector", the user shouldn't use this copy itself if he doesn't want to do bugs, but in BOOST_FOREACH it's okay:
I change the mutex to a recursive_mutex
I change the lock to an unique_lock
and:
MyContainer(const MyContainer& other) :
m_vector(other.vec),
m_lock(*other.m_lock.mutex())
{
}
With C++11
Thanks to Chris Glover on the boost mailling list, a C++11 solution:
You can't do what you are trying to do in C++03. To accomplish it, you
need C++11 move semantics to be able to move the MyContainer out of the Get
function. Even without using BOOST_FOREACH, the following code fails;
GetContainer<int> getter(v, m);
MyContainer<int> c = getter.Get(); // <-- Error.
Here's an example with the necessary changes; I changed the scoped_lock to
a unique_lock and added a move constructor.
template <typename T>
class MyContainer
{
public:
[...]
MyContainer(MyContainer&& other)
: m_vector(other.m_vector)
{
m_lock = std::move(other.m_lock);
other.m_vector = nullptr;
}

Persistent expression templates with unique_ptr and matrices

I want to use expression templates to create a tree of objects that persists across statement. Building the tree initially involves some computations with the Eigen linear algebra library. The persistent expression template will have additional methods to compute other quantities by traversing the tree in different ways (but I'm not there yet).
To avoid problems with temporaries going out of scope, subexpression objects are managed through std::unique_ptr. As the expression tree is built, the pointers should be propagated upwards so that holding the pointer for the root object ensures all objects are kept alive. The situation is complicated by the fact that Eigen creates expression templates holding references to temporaries that go out of scope at the end of the statement, so all Eigen expressions must be evaluated while the tree is being constructed.
Below is a scaled-down implementation that seems to work when the val type is an object holding an integer, but with the Matrix type it crashes while constructing the output_xpr object. The reason for the crash seems to be that Eigen's matrix product expression template (Eigen::GeneralProduct) gets corrupted before it is used. However, none of the destructors either of my own expression objects or of GeneralProduct seems to get called before the crash happens, and valgrind doesn't detect any invalid memory accesses.
Any help will be much appreciated! I'd also appreciate comments on my use of move constructors together with static inheritance, maybe the problem is there somewhere.
#include <iostream>
#include <memory>
#include <Eigen/Core>
typedef Eigen::MatrixXi val;
// expression_ptr and derived_ptr: contain unique pointers
// to the actual expression objects
template<class Derived>
struct expression_ptr {
Derived &&transfer_cast() && {
return std::move(static_cast<Derived &&>(*this));
}
};
template<class A>
struct derived_ptr : public expression_ptr<derived_ptr<A>> {
derived_ptr(std::unique_ptr<A> &&p) : ptr_(std::move(p)) {}
derived_ptr(derived_ptr<A> &&o) : ptr_(std::move(o.ptr_)) {}
auto operator()() const {
return (*ptr_)();
}
private:
std::unique_ptr<A> ptr_;
};
// value_xpr, product_xpr and output_xpr: expression templates
// doing the actual work
template<class A>
struct value_xpr {
value_xpr(const A &v) : value_(v) {}
const A &operator()() const {
return value_;
}
private:
const A &value_;
};
template<class A,class B>
struct product_xpr {
product_xpr(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) :
a_(std::move(a).transfer_cast()), b_(std::move(b).transfer_cast()) {
}
auto operator()() const {
return a_() * b_();
}
private:
derived_ptr<A> a_;
derived_ptr<B> b_;
};
// Top-level expression with a matrix to hold the completely
// evaluated output of the Eigen calculations
template<class A>
struct output_xpr {
output_xpr(expression_ptr<derived_ptr<A>> &&a) :
a_(std::move(a).transfer_cast()), result_(a_()) {}
const val &operator()() const {
return result_;
}
private:
derived_ptr<A> a_;
val result_;
};
// helper functions to create the expressions
template<class A>
derived_ptr<value_xpr<A>> input(const A &a) {
return derived_ptr<value_xpr<A>>(std::make_unique<value_xpr<A>>(a));
}
template<class A,class B>
derived_ptr<product_xpr<A,B>> operator*(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) {
return derived_ptr<product_xpr<A,B>>(std::make_unique<product_xpr<A,B>>(std::move(a).transfer_cast(), std::move(b).transfer_cast()));
}
template<class A>
derived_ptr<output_xpr<A>> eval(expression_ptr<derived_ptr<A>> &&a) {
return derived_ptr<output_xpr<A>>(std::make_unique<output_xpr<A>>(std::move(a).transfer_cast()));
}
int main() {
Eigen::MatrixXi mat(2, 2);
mat << 1, 1, 0, 1;
val one(mat), two(mat);
auto xpr = eval(input(one) * input(two));
std::cout << xpr() << std::endl;
return 0;
}
Your problem appears to be that you are using someone else's expression templates, and storing the result in an auto.
(This happens in product_xpr<A>::operator(), where you call *, which if I read it right, is an Eigen multiplication that uses expression templates).
Expression templates are often designed to presume the entire expression will occur on a single line, and it will end with a sink type (like a matrix) that causes the expression template to be evaluated.
In your case, you have a*b expression template, which is then used to construct an expression template return value, which you later evaluate. The lifetime of temporaries passed to * in a*b are going to be over by the time you reach the sink type (matrix), which violates what the expression templates expect.
I am struggling to come up with a solution to ensure that all temporary objects have their lifetime extended. One thought I had was some kind of continuation passing style, where instead of calling:
Matrix m = (a*b);
you do
auto x = { do (a*b) pass that to (cast to matrix) }
replace
auto operator()() const {
return a_() * b_();
}
with
template<class F>
auto operator()(F&& f) const {
return std::forward<F>(f)(a_() * b_());
}
where the "next step' is passed to each sub-expression. This gets trickier with binary expressions, in that you have to ensure that the evaluation of the first expression calls code that causes the second sub expression to be evaluated, and then the two expressions are combined, all in the same long recursive call stack.
I am not proficient enough in continuation passing style to untangle this knot completely, but it is somewhat popular in the functional programming world.
Another approach would be to flatten your tree into a tuple of optionals, then construct each optional in the tree using a fancy operator(), and manually hook up the arguments that way. Basically do manual memory management of the intermediate values. This will work if the Eigen expression templates are either move-aware or do not have any self-pointers, so that moving at the point of construction doesn't break things. Writing that would be challenging.
Continuation passing style, suggested by Yakk, solves the problem and isn't too insane (not more insane than template metaprogramming in general anyhow). The double lambda evaluation for the arguments of binary expressions can be tucked away in a helper function, see binary_cont in the code below. For reference, and since it's not entirely trivial, I'm posting the fixed code here.
If somebody understands why I had to put a const qualifier on the F type in binary_cont, please let me know.
#include <iostream>
#include <memory>
#include <Eigen/Core>
typedef Eigen::MatrixXi val;
// expression_ptr and derived_ptr: contain unique pointers
// to the actual expression objects
template<class Derived>
struct expression_ptr {
Derived &&transfer_cast() && {
return std::move(static_cast<Derived &&>(*this));
}
};
template<class A>
struct derived_ptr : public expression_ptr<derived_ptr<A>> {
derived_ptr(std::unique_ptr<A> &&p) : ptr_(std::move(p)) {}
derived_ptr(derived_ptr<A> &&o) = default;
auto operator()() const {
return (*ptr_)();
}
template<class F>
auto operator()(F &&f) const {
return (*ptr_)(std::forward<F>(f));
}
private:
std::unique_ptr<A> ptr_;
};
template<class A,class B,class F>
auto binary_cont(const derived_ptr<A> &a_, const derived_ptr<B> &b_, const F &&f) {
return a_([&b_, f = std::forward<const F>(f)] (auto &&a) {
return b_([a = std::forward<decltype(a)>(a), f = std::forward<const F>(f)] (auto &&b) {
return std::forward<const F>(f)(std::forward<decltype(a)>(a), std::forward<decltype(b)>(b));
});
});
}
// value_xpr, product_xpr and output_xpr: expression templates
// doing the actual work
template<class A>
struct value_xpr {
value_xpr(const A &v) : value_(v) {}
template<class F>
auto operator()(F &&f) const {
return std::forward<F>(f)(value_);
}
private:
const A &value_;
};
template<class A,class B>
struct product_xpr {
product_xpr(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) :
a_(std::move(a).transfer_cast()), b_(std::move(b).transfer_cast()) {
}
template<class F>
auto operator()(F &&f) const {
return binary_cont(a_, b_,
[f = std::forward<F>(f)] (auto &&a, auto &&b) {
return f(std::forward<decltype(a)>(a) * std::forward<decltype(b)>(b));
});
}
private:
derived_ptr<A> a_;
derived_ptr<B> b_;
};
template<class A>
struct output_xpr {
output_xpr(expression_ptr<derived_ptr<A>> &&a) :
a_(std::move(a).transfer_cast()) {
a_([this] (auto &&x) { this->result_ = x; });
}
const val &operator()() const {
return result_;
}
private:
derived_ptr<A> a_;
val result_;
};
// helper functions to create the expressions
template<class A>
derived_ptr<value_xpr<A>> input(const A &a) {
return derived_ptr<value_xpr<A>>(std::make_unique<value_xpr<A>>(a));
}
template<class A,class B>
derived_ptr<product_xpr<A,B>> operator*(expression_ptr<derived_ptr<A>> &&a, expression_ptr<derived_ptr<B>> &&b) {
return derived_ptr<product_xpr<A,B>>(std::make_unique<product_xpr<A,B>>(std::move(a).transfer_cast(), std::move(b).transfer_cast()));
}
template<class A>
derived_ptr<output_xpr<A>> eval(expression_ptr<derived_ptr<A>> &&a) {
return derived_ptr<output_xpr<A>>(std::make_unique<output_xpr<A>>(std::move(a).transfer_cast()));
}
int main() {
Eigen::MatrixXi mat(2, 2);
mat << 1, 1, 0, 1;
val one(mat), two(mat), three(mat);
auto xpr = eval(input(one) * input(two) * input(one) * input(two));
std::cout << xpr() << std::endl;
return 0;
}

Possible to write the code once for a specific set of different types?

I have a template class TC who's constructor takes parameters who's values are dependent on, as well as being of type Tn.
So, I want to create a helper template function htf that will call the same functions of a Tn object to generate a TC for a set of types X0 to Xn. The helper function takes only one parameter from that set. Is it possible, perhaps with variadic templates, to write the function once for the set of types, instead of having to write the same function over and over again for each type?
Now, I could just use a template to allow all types, but I don't want that as there may be another function with the same name written for a specific type later that's not based on this TC. And, IIRC I think SFINAE works with member functions, not pure functions.
This is just an idea in my head at the moment, that's why the question is very general. However, here is roughly the code I'm thinking of, simplified, in an more concrete and in an over generalized fashion:
struct X0
{
int value;
int& fn() { return value; }
};
struct X1
{
double value;
double& fn() { return value; }
};
struct X2
{
float value;
float& fn() { return value; }
};
struct Y0 // don't accept this class in helper function
{
int value;
int& fn() { return value; }
};
template<typename T1, typename Tn>
class TC
{
T1* m_pT1;
Tn* m_pTn;
TC(T1* pT1, Tn* pTn) : m_pT1(pT1), m_pTn(pTn) {}
friend TC htf(Tn& tn);
public:
~TC() {}
};
// concrete functions:
TC<int, X0> htf(C0& x) { return TC<int, X0>(&x.fn(), &x); }
TC<double, X1> htf(C1& x) { return TC<double, X1>(&x.fn(), &x); }
TC<float, X2> htf(C2& x) { return TC<float, X2>(&x.fn(), &x); }
// or in an over generalized template function but it'll accept
// Y0 and others which I don't want:
template<typename X>
auto htf(X& x) -> TC<decltype(x.fn()), X>
{
return TC<decltype(x.fn()), X>(&x.fn(), &x);
}
So the htf function that I want is to work for classes X0, X1, and X2, but not Y0. However, I don't want it to interfere with any other function called htf that takes a parameter of type Y0, or any other type for that matter.
Additional
Is it possible to make it so that the collection of accepted classes can also include template classes taking an specified (or unspecified) number of parameters?
Write a function that is only enabled when a trait is true, then specialize it for all the desired types.
template<typename T>
struct enable_htf : std::false_type { };
template<>
struct enable_htf<X0> : std::true_type { };
template<>
struct enable_htf<X1> : std::true_type { };
// etc.
template<typename T, bool enable = enable_htf<T>::value>
struct htf_helper { };
template<typename T>
struct htf_helper<T, true>
{
using type = TC<decltype(std::declval<T&>().fn()), T>;
};
template<typename X>
typename htf_helper<X>::type
htf(X& x)
{
return { &x.fn(), &x };
}
But it seems you want something like this instead:
template<typename Needle, typename... Haystack>
struct is_one_of;
template<typename Needle, typename Head, typename... Tail>
struct is_one_of<Needle, Head, Tail...>
: conditional<is_same<Needle, Head>::value, true_type,
is_one_of<Needle, Tail...>>::type
{ };
template<typename Needle>
struct is_one_of<Needle> : false_type
{ };
template<typename X,
typename Requires = typename enable_if<is_one_of<X, X0, X1, X2>::value>::type>
auto
htf(X& x) -> TC<decltype(x.fn()), X>
{
return { &x.fn(), &x };
}
But personally I don't consider that clearer, even if is_one_of is reusable elsewhere.
This is an even more simplified version of my original question, but it relates to enabling a template function based on the type passed to it being part of a list of accepted types.
class A{};
class B{};
class C{};
class D{};
class collection1 : A, B, C {};
class collection2 : D {};
template<typename X>
typename std::enable_if<std::is_base_of<X, collection1>::value, X>::type fn(X x)
{
return X();
}
Then the following would work appropriately:
fn(A()); // works
fn(B()); // works
fn(C()); // works
fn(D()); // compile time failure
Having a 2nd function like this:
template<typename X>
typename std::enable_if<std::is_base_of<X, collection2>::value, X>::type fn(X x)
{
return X();
}
Would result in:
fn(A()); // works
fn(B()); // works
fn(C()); // works
fn(D()); // works
Using this method, I can enable function fn to work with types I want and not others and I can write the list with ease. Also, this should be faster than iterating through a list of variadic template parameters.
Thanks Jonathan Wakely, you helped a lot in my thought process. I just thought that this is simpler and can be made even clearer if I use a helper template which would encapsulate the enable_if clause which would be good as I have many other functions that would require this.
Additional
Looks like this answer isn't good enough as I need to be able to determine if a template class is in the collection I'm looking for.

Does/would c++11/14 support something like vector<auto>

I am wondering if c++11/c++14 would/already support something like vector<auto>?
If not, Is there any reason?
It's not supported directly, and not immediately clear exactly what you want it to do.
Comments have already mentioned a couple of possibilities (such as Boost any and variant classes) for creating heterogeneous collections. I hope this isn't what you were after, because heterogeneous collections fit poorly with C++ so using them is ugly and clumsy. I suppose there are cases/situations where these really would be the best choices available, but at least in my experience, those cases are fairly rare.
Another possible interpretation of what you might want would be a vector that (like auto in general) holds exactly one type, but that type is deduced from the initializer, so if you initialized the vector from some ints, you'd get a vector<int>, and if you initialized it from some strings, you'd get a vector<string>, and so on. Although the language doesn't support that directly, it is pretty easy to simulate it to at least some degree. Template classes can't/don't ever deduce template parameters, but template functions do/can. Therefore, we can create a tiny function template to take some initializers, deduce their type, and return a vector of that type. For example:
template <class T>
std::vector<T> make_vector(std::initializer_list<T> init) {
return std::vector<T>(init);
}
This returns a vector<T> (with T deduced from the type of data in the initializer list), so you can do things like:
auto a = make_vector({ 1, 2, 3, 4 }); // a -> vector<int>
auto b = make_vector({ 1.0, 2.0, 3.0 }); // b -> vector<double>
auto c = make_vector({ "1"s, "2"s, "3"s }); // c -> vector<std::string>
That last one requires a user-defined literal operator that's new in C++14 (which many compilers don't yet support). The rest should be fine with C++11.
There has also been some discussion (and a proposal in N3602) of adding a capability (perhaps to C++17) where you'd be able to define something like the make_vector above, but as something like a templated constructor for the class. This would let you use argument deduction on the constructor to deduce the template parameter for the class as a whole, so you'd be able to do something like:
X x(1); // deduces as X<int>
X x(2.0) // deduces as X<double>
Warning though: this has been proposed but not accepted. It may (easily) never be accepted--and even if it is, it may be altered significantly before that happens.
No, not in C++11 or C++14, which are already finished and published.
But it's possible that vector<auto> and similar things like tuple<auto...> will be in C++17 as part of the Concepts work.
It follows quite naturally from the fact that std::vector<T> can be used in function templates and class template partial specializations where T is a template parameter, and also from the fact that polymorphic lambdas allow auto as a function parameter type (which is shorthand for a function template with deduced parameters).
The Concepts TS allows a "generic function" to be declared like:
auto func(auto arg);
Since you can have a function template like this:
template<typename T>
auto func(std::vector<T> v);
it makes sense to extend the generic function syntax to allow:
auto func(std::vector<auto> v);
and once you allow that in a function declaration, it should also be possible to allow it in variable declarations:
std::vector<auto> v = function_returning_vector_of_something();
The reason it isn't in C++11 is that auto was new, and it would have been too ambitious to try and make it do too much. In C++14 polymorphic lambdas were new, and again, expanding the uses of auto any further would have been ambitious.
For C++17 we have more experience with using auto in real code, and compiler writers are familiar with implementing it and know what is possible without too much effort.
A boost::any can store an instance of any type that can be copied, which is a lot of types.
In order to get the data out of your any, you have to know the exact type you stored in it.
Writing a simple any isn't hard:
#include <memory>
#include <utility>
struct any_internal {
virtual any_internal* clone() const = 0;
virtual ~any_internal() {};
};
template<class T>
struct any_details;
class any {
std::unique_ptr<any_internal> internal;
public:
any() = default;
any( any && ) = default;
any( any const&& o):any(o) {}
any( any & o ):any( const_cast<any const&>(o) ) {}
any& operator=( any && ) = default;
any& operator=( any const&& o ) { return this->operator=( o ); };
any& operator=( any & o ) { return this->operator=( const_cast<any const&>(o) ); };
any( any const& o ):internal( o.internal?o.internal->clone():nullptr ) {}
any& operator=( any const& o ) {
any tmp(o);
using std::swap;
swap( internal, tmp.internal );
return *this;
}
template<class U>
void reset( U&& o );
template<class U, class... Args>
void emplace( Args&&... args );
template<class U>
any( U&& o );
template<class U>
any& operator=(U&& o);
template<class T> T* get();
template<class T> T const* get() const;
template<class T> T* fast_get();
template<class T> T const* fast_get() const;
explicit operator bool() const { return internal!=nullptr; }
};
template<class T>
struct any_details : any_internal {
T t;
template<class...Args>
any_details( Args&&... args ):t(std::forward<Args>(args)...) {}
any_internal* clone() const override { return new any_details<T>{t}; }
};
template<class U, class... Args>
void any::emplace( Args&&... args ) {
internal.reset( new any_details<U>( std::forward<Args>(args)... ) );
}
template<class U>
void any::reset( U&& o ) {
emplace<typename std::decay<U>::type>( std::forward<U>(o) );
}
template<class U>
any::any( U&& o ) {
reset( std::forward<U>(o) );
}
template<class U>
any& any::operator=(U&& o) {
reset( std::forward<U>(o) );
return *this;
}
template<class T> T* any::get() {
auto* r = dynamic_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
template<class T> T const* any::get() const {
auto* r = dynamic_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
template<class T> T* any::fast_get() {
auto* r = static_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
template<class T> T const* any::fast_get() const {
auto* r = static_cast< any_details<T>* >( internal.get() );
if (r) return &r->t;
return nullptr;
}
and a std::vector<any> behaves much like you might want a std::vector<auto> to do.
Increased efficiency can be achieved via small buffer optimizations (ie, store the T within the any if the t is small, instead of using the heap).
You'd probably also want to split get from fast_get, where get does a dynamic_cast and fast_get does a static_cast, again for efficiency. (When you know for certain, you can fast_get)
Basically this is a gussied up void*.

Is there a better way in C++11 to construct classes on the stack

If I have two classes D1 and D2 that both derive from class Base, and I want to construct a particular one based on say, a boolean variable, there are various well known techniques, eg use a factory, or use smart pointers.
For example,
std::unique_ptr<Base> b;
if (flag)
{
b.reset(new D1());
}
else
{
b.reset(new D2());
}
But this uses the heap for allocation, which is normally fine but I can think of times where it would be good to avoid the performance hit of a memory allocation.
I tried:
Base b = flag ? D1() : D2(); // doesn’t compile
Base& b = flag ? D1() : D2(); // doesn’t compile
Base&& b = flag ? D1() : D2(); // doesn’t compile
Base&& b = flag ? std::move(D1()) : std::move(D2()); // doesn’t compile
My intention is that D1 or D2 whichever is chosen is constructed on the stack, and its lifetime ends when b goes out of scope. Intuitively, I feel there should be a way to do it.
I played with lambda functions and found that this works:
Base&& b = [j]()->Base&&{
switch (j)
{
case 0:
return std::move(D1());
default:
return std::move(D2());
}
}();
Why it doesn’t suffer from the same issues as the others that do not compile I do not know.
Further, it would only be suitable for classes that are inexpensive to copy, because despite my explicit request to use move, it does I think still call a copy constructor. But if I take away the std::move, I get a warning!
I feel this is closer to what i think should be possible but it still has some issues:
the lambda syntax is not friendly to old-timers who havent yet
embraced the new features of the language ( myself included)
the copy constructor call as mentioned
Is there a better way of doing this?
If you know all the types, you can use a Boost.Variant, as in:
class Manager
{
using variant_type = boost::variant<Derived1, Derived2>;
struct NameVisitor : boost::static_visitor<const char*>
{
template<typename T>
result_type operator()(T& t) const { return t.name(); }
};
public:
template<typename T>
explicit Manager(T t) : v_(std::move(t)) {}
template<typename T>
Manager& operator=(T t)
{ v_ = std::move(t); return *this; }
const char* name()
{ return boost::apply_visitor(NameVisitor(), v_); }
private:
variant_type v_;
};
Note: by using variant, you no longer need a base class or virtual functions.
The way you are trying to do it, you are going to get a dangling reference. Having the std::move is just hiding that.
Generally I just structure the code so that the logic is in a separate function. That is, instead of
void f(bool flag)
{
Base &b = // some magic to choose which derived class to instantiate
// do something with b
}
I do
void doSomethingWith(Base &b)
{
// do something with b
}
void f(bool flag)
{
if (flag) {
D1 d1;
doSomethingWith(d1);
}
else {
D2 d2;
doSomethingWith(d2);
}
}
However, if that doesn't work for you, you can use a union inside a class to help manage it:
#include <iostream>
using std::cerr;
struct Base {
virtual ~Base() { }
virtual const char* name() = 0;
};
struct Derived1 : Base {
Derived1() { cerr << "Constructing Derived1\n"; }
~Derived1() { cerr << "Destructing Derived1\n"; }
virtual const char* name() { return "Derived1"; }
};
struct Derived2 : Base {
Derived2() { cerr << "Constructing Derived2\n"; }
~Derived2() { cerr << "Destructing Derived2\n"; }
virtual const char* name() { return "Derived2"; }
};
template <typename B,typename D1,typename D2>
class Either {
union D {
D1 d1;
D2 d2;
D() { }
~D() { }
} d;
bool flag;
public:
Either(bool flag)
: flag(flag)
{
if (flag) {
new (&d.d1) D1;
}
else {
new (&d.d2) D2;
}
}
~Either()
{
if (flag) {
d.d1.~D1();
}
else {
d.d2.~D2();
}
}
B& value()
{
if (flag) {
return d.d1;
}
else {
return d.d2;
}
}
};
static void test(bool flag)
{
Either<Base,Derived1,Derived2> either(flag);
Base &b = either.value();
cerr << "name=" << b.name() << "\n";
}
int main()
{
test(true);
test(false);
}
gives this output:
Constructing Derived1
name=Derived1
Destructing Derived1
Constructing Derived2
name=Derived2
Destructing Derived2
You can ensure you have enough space for allocating either on the stack with std::aligned_storage. Something like:
// use macros for MAX since std::max is not const-expr
std::aligned_storage<MAX(sizeof(D1), sizeof(D2)), MAX(alignof(D1), alignof(D2))> storage;
Base* b = nullptr;
if (flag)
b = new (&storage) D1();
else
b = new (&storage) D2();
You can make a wrapper type for aligned_storage that just takes two types and does the maximum of size/alignment of the two without needing to repeat yourself in the code using it. You can emulate aligned_storage for non-over-aligned types fairly trivially too if you need C++98 support. The custom type without over-aligned support would be something like:
template <typename T1, typename T2>
class storage
{
union
{
double d; // to force strictest alignment (on most platforms)
char b[sizeof(T1) > sizeof(T2) ? sizeof(T1) : sizeof(T2)];
} u;
};
And that can be given protections against copies/moves if you so wish. It can even be turned into a simplified Boost.Variant with relatively little work.
Note that with this approach (or some of the others), destructors will not be called automatically on your class and you must call them yourself. If you want RAII patterns to apply here, you can extend the example class above to store a deleter function that is bound during construction into the space.
template <typename T1, typename T2>
class storage
{
using deleter_t = void(*)(void*);
std::aligned_storage<
sizeof(T1) > sizeof(T2) ? sizeof(T1) : sizeof(T2),
alignof(T1) > alignof(T2) ? alignof(T1) : alignof(T2)
> space;
deleter_t deleter = nullptr;
public:
storage(const storage&) = delete;
storage& operator=(const storage&) = delete;
template <typename T, typename ...P>
T* emplace(P&&... p)
{
destroy();
deleter = [](void* obj){ static_cast<T*>(obj)->~T(); }
return new (&space) T(std::forward<P>(p)...);
}
void destroy()
{
if (deleter != nullptr)
{
deleter(&space);
deleter = nullptr;
}
}
};
// usage:
storage<D1, D2> s;
B* b = flag ? s.emplace<D1>() : s.emplace<D2>();
And of course that can all be done in C++98, just with a lot more work (especially in terms of emulating the emplace function).
How about
B&&b = flag ? static_cast<B&&>(D1()) : static_cast<B&&>(D2());
If you just need them to be freed when the reference goes out of scope, you could implement another simple class (maybe named DestructorDecorator) that points to the object (D1 or D2). And then you just have to implement ~DestructorDecorator to call the destructor of D1 or D2.
You haven't mentioned it, your flag is known at compile time?
As far as a compile-time flag is concerned, you can use template magic to deal with the conditional construction of the class:
First, declaring a template create_if which takes two types and a boolean:
template <typename T, typename F, bool B> struct create_if {};
Second, specializing create_if for true and false values:
template <typename T, typename F> struct create_if<T, F, true> { using type = T; };
template <typename T, typename F> struct create_if<T, F, false> { using type = F; };
Then, you can do this:
create_if<D1, D2, true>::type da; // Create D1 instance
create_if<D1, D2, false>::type db; // Create D2 instance
You can change the boolean literals with your compile-time flag or with a constexpr function:
constexpr bool foo(const int i) { return i & 1; }
create_if<D1, D2, foo(100)>::type dc; // Create D2 instance
create_if<D1, D2, foo(543)>::type dd; // Create D1 instance
This is valid only if the flag is known at compile time, I hope it helps.
Live example.

Resources