I want to add a Foo object to a std::vector but I don't want to create a temporary object to add to the vector because that would call Foo::~Foo() once the temporary object goes out of scope. Do I have to use new and make the vector store Foo pointers, or is there another way?
What I don't want to do:
void FooHandler::AddFoo(int a, int b, int c) {
Foo foo(a, b, c);
vectorOfFoos.push_back(foo);
} //foo goes out of scope so Foo::~Foo() is called
Would these work?
//Foo has an implicit constructor which takes a FooSettings object
struct FooSettings {
public:
int a;
int b;
int c;
};
void FooHandler::AddFoo(int a, int b, int c) {
vectorOfFoos.push_back(Foo(a, b, c));
} //is Foo::~Foo() called here?
void FooHandler::AddFoo(FooSettings settings) {
vectorOfFoos.push_back(settings);
} //is Foo::~Foo() called here?
Both of your solutions will involve the creation of a temporary. You can use emplace_back instead of push_back to construct the Foo instance in-place rather than copying it in to the vector.
void FooHandler::AddFoo(int a, int b, int c) {
vectorOfFoos.emplace_back(a,b,c);
}
Related
For example:
std::unique_ptr<Box[]> Boxes(new Box[5]);
std::function<int(doube, double)> funcobj;
But for any variable x, decltype(x) cannot be T[] or call signature R(A1,...)
Thank you all for your helpful discussion.
Now I understand that both are truly types. You can use them in typedef declaration. But they are special you cannot use them as normal types. Here is an example to use these types.
typedef int function_type(int, int);
typedef char char_array[];
// char_array arr; // Not allowed
char_array str = "hello";
function_type add; // like function declaration;
// function add defined here.
int add(int a, int b) {
return a+b;
};
Are the std::move at the end of the following function needed (to avoid copying the vectors)?
std::pair<vector<int>, vector<int>> f()
{
vector<int> a, b;
...
return std::make_pair(std::move(a), std::move(b));
}
Or will the compiler move the vectors even if the std::move are omitted?
The std::moves are necessary.
If what you suggest were allowed, the following code would be (surprisingly) broken since both arguments to std::make_pair would be moved-from:
std::vector<int> a;
// populate a
return std::make_pair(a, a);
I wonder why this choice is made. It would allow to write many functions in a very clear and neat way.. for instance:
int greatestCommonDivisor(int a, int b)
{
if (b > a)
std::tie(a, b) = { b, a };
while (b > 0)
std::tie(a, b) = { b, a % b };
return a;
}
std::initializer_list is a homogeneous collection of items, while std::tuple is heterogeneous. The only case where it makes sense to define a std::tuple::operator= for std::initializer_list is when the tuple is homogeneous and has the same size as the initializer list, which is a rare occurrence.
(Additional information in this question.)
Solution/workaround: you can use std::make_tuple instead:
int greatestCommonDivisor(int a, int b)
{
if (b > a)
std::tie(a, b) = std::make_tuple(b, a);
while (b > 0)
std::tie(a, b) = std::make_tuple(b, a % b);
return a;
}
...or std::tuple's constructor in C++17 (thanks to Template argument deduction for class templates):
int greatestCommonDivisor(int a, int b)
{
if (b > a)
std::tie(a, b) = std::tuple{b, a};
while (b > 0)
std::tie(a, b) = std::tuple{b, a % b};
return a;
}
Why does
std::tie(a,b) = {b, a};
not compile?
{} on the right hand side of an assignment can only call a non-explicit constructor of an argument of operator=.
The operator= overloads available are:
tuple& operator=( const tuple& other );
tuple& operator=( tuple&& other );
template< class... UTypes >
tuple& operator=( const tuple<UTypes...>& other );
template< class... UTypes >
tuple& operator=( tuple<UTypes...>&& other );
template< class U1, class U2 >
tuple& operator=( const pair<U1,U2>& p );
template< class U1, class U2 >
tuple& operator=( pair<U1,U2>&& p );
The template operator overloads cannot deduce their types from {} (note: this may change in C++17), leaving:
tuple& operator=( const tuple& other );
tuple& operator=( tuple&& other );
where tuple is std::tuple<int&, int&> in this case.
The tuple constructor for tuple<Ts...> that perfect forwards element-wise construction is explicit (#3 on that list). {} will not call an explicit constructor.
The conditionally non-explicit constructor takes Ts const&...; it does not exist if the Ts are non-copyable, and int& is non-copyable.
So there are no viable types to construct from {int&, int&}, and overload resolution fails.
Why does the standard not fix this? Well, we can do it ourselves!
In order to fix this, we'd have to add a special (Ts...) non-explicit constructor to tuple that only exists if the Ts types are all references.
If we write a toy tuple:
struct toy {
std::tuple<int&, int&> data;
toy( int& a, int& b ):data(a,b) {} // note, non-explicit!
};
toy toy_tie( int& a, int& b ) { return {a,b}; }
and use it, you'll notice that
std::tie(a, b) = {b, a};
compiles and runs.
However,
std::tie(a, b) = { b, a % b };
does not, as a%b cannot be bound to int&.
We can then augment toy with:
template<class...>
toy& operator=( std::tuple<int, int> o ) {
data = o;
return *this;
}
(+ defaulted special member functions. template<class...> ensures it has lower priority than the special member functions, as it should).
This which lets assign-from {int,int}. We then run it and... get the wrong result. The gcd of 5,20 is 20. What went wrong?
toy_tie(a, b) = std::tie( b, a );
with both a and b bound to references is not safe code, and that is what
toy_tie(a, b) = { b, a };
does.
In short, doing this right is tricky. In this case, you need to take a copy of the right hand side before assigning to be safe. Knowing when to take a copy and when not to is also tricky.
Having this work implicitly looks error prone. So it is, in a sense, accidental that it doesn't work, but fixing it (while possible) looks like a bad idea.
live example.
I have re-arranged an example regarding the std::forward with template.
I have used a wrapper function and everything is fine, if i declare it as void function. It works as expected.
#include<iostream>
using namespace std;
template <typename T, typename U>
auto summation(T const &a, U const& b) -> decltype(T{}, U{}) {
cout << "call by lvalue" << endl;
return a+b;
}
template <typename T, typename U>
auto summation(T&& a, U && b) -> decltype(T{},U{}) {
cout << "call by rvalue" << endl;
return a+b;
}
template<typename T,typename U> void func(T&& a, U && b) {
summation(forward<T>(a), forward<U>(b));
}
int main() {
int x = 10;
double y = 20;
func(x,y);
func(10,20);
}
but if I want to return a type from a wrapper function, no matter what I used, I got error on lvalues function call ONLY, fund(x,y), stating "....function does not match the arguments"... the other fund(10,20) works.
template<typename T,typename U> auto func(T&& a, U && b) -> decltype(T{}, U{}) {
return summation(forward<T>(a), forward<U>(b));
}
and even using c++14 decltype(auto) for deducing the return type of forwarding functions and similar wrappers
template<typename T,typename U> decltype(auto) func(T&& a, U && b) {
return summation(forward<T>(a), forward<U>(b));
}
it does not work either, stating "decline(type) is C++o1 extension..." that, thank you compiler, but it does help.
One non sense horrible solution is declare the return type or T or U as return type. This compiles even if I got a warning stating "Reference to stack memory associated to local variable returned"
template<typename T,typename U> U func(T&& a, U && b) {
auto res = summation(forward<T>(a), forward<U>(b));
return res;
}
the return type of std::forward given (t) the object to be forwarded is
static_cast<T&&>(t)
therefore it the first solution with auto should work but it does not.
Any suggestion on this ?
Thanks for any help
decltype means the type of the expression given in its argument. So
decltype(T {}, U {})
will be the type of the expression T{}, U{}. You have the comma operator here, and so the type of the expression is the type of the expression after the comma, which is U{}, hence decltype (T{}, U{}) gives you type U (more precisely, U &&, I guess, since it is an rvalue).
What you want is
decltype(T{} + U{})
or
decltype(a+b)
(thanks to Jonathan Wakely, see comments).
I'm doing a D bridge to a C library, and this has come up with the C code using typedef'd enums that it refers to like a constant, but can name it for function arguments and the like. Example:
enum someLongNameThatTheCLibraryUses
{
A,
B,
}
Currently, I must refer to it like so:
someLongNameThatTheCLibraryUses.A;
But I would rather:
A;
I could do this:
alias someLongNameThatTheCLibraryUses a;
a.A;
But I don't want to do that in the library module, so I'd have to do it where it's used, which would be annoying.
Is there a way to do this?
If you would like type safety with anonymous enums, you can create a new distinct type using typedef, and use it as the base type of the anonymous enum. Example:
typedef int A;
enum : A
{
a1,
a2,
a3
}
typedef int X;
enum : X
{
x1,
x2,
x3
}
void main()
{
A a;
X x;
x = a; // Error: cannot implicitly convert expression (a) of type A to X
}