Uniform initialization by tupleWhat is the easiest way to initialize a std::vector with hardcoded elements?Why can't I make objects in C++ have data-members that are other objects?Pretty-print C++ STL containersC++ vector::push_back using default copy constructorC++0x uniform initialization “oddity”Why doesn't emplace_back() use uniform initialization?Why does 'std::vector<int> b2;' create a 1-element vector, and not a 2-element one?Does std::vector<Object> reserve method need a copy constructor for Object class?std::make_map? uniform initializationVector push_back error when compiling
Filtering fine silt/mud from water (not necessarily bacteria etc.)
Is this floating-point optimization allowed?
Find values of x so that the matrix is invertible
TikZ Can I draw an arrow by specifying the initial point, direction, and length?
Can I intentionally omit previous work experience or pretend it doesn't exist when applying for jobs?
What is the commentary on Leviticus 21:2-4 - why is wife not included on the list
I quit, and boss offered me 3 month "grace period" where I could still come back
What is temperature on a quantum level?
Find the wrong number in the given series: 6, 12, 21, 36, 56, 81?
Was adding milk to tea started to reduce employee tea break time?
Report how much space is used and available in storage in ZFS on FreeBSD
Why does Hellboy file down his horns?
Why hasn't the U.S. government paid war reparations to any country it attacked?
Did any of the founding fathers anticipate Lysander Spooner's criticism of the constitution?
As a DM, how to avoid unconscious metagaming when dealing with a high AC character?
How might the United Kingdom become a republic?
Military Weapon System
What happens if you Dissonant Whispers a Hydra?
Supporting developers who insist on using their pet language
How to check the quality of an audio sample?
Players of unusual orchestral instruments
How to determine port and starboard on a rotating wheel space station?
Why did the Japanese attack the Aleutians at the same time as Midway?
Ambiguous sentences: How to tell when they need fixing?
Uniform initialization by tuple
What is the easiest way to initialize a std::vector with hardcoded elements?Why can't I make objects in C++ have data-members that are other objects?Pretty-print C++ STL containersC++ vector::push_back using default copy constructorC++0x uniform initialization “oddity”Why doesn't emplace_back() use uniform initialization?Why does 'std::vector<int> b2;' create a 1-element vector, and not a 2-element one?Does std::vector<Object> reserve method need a copy constructor for Object class?std::make_map? uniform initializationVector push_back error when compiling
.everyoneloves__top-leaderboard:empty,.everyoneloves__mid-leaderboard:empty,.everyoneloves__bot-mid-leaderboard:empty margin-bottom:0;
Today, I arrived at a situation, where I have a vector of tuples, where the tuples might contain several entries. Now I wanted to convert my vector of tuples to a vector of objects, such that the entries of the tuples will exactly match the uniform initialization of my object.
The following code does the job for me, but it is a bit clumsy. I'm asking myself if it might be possible to derive a generic solution that can construct the Objects if the tuples matches exactly the uniform initialization order of the objects.
This might be a very desirable functionality, when the number of parameters to pass grows.
#include <vector>
#include <tuple>
#include <string>
#include <algorithm>
struct Object
std::string s;
int i;
double d;
;
int main()
std::vector<std::tuple<std::string, int, double>> values = "A",0,0.,"B",1,1. ;
std::vector<Object> objs;
std::transform(values.begin(), values.end(), std::back_inserter(objs), [](auto v)->Object
// This might get tedious to type, if the tuple grows
return std::get<0>(v), std::get<1>(v), std::get<2>(v) ;
// This is my desired behavior, but I don't know what magic_wrapper might be
// return magic_wrapper(v);
);
return EXIT_SUCCESS;
c++ stl stl-algorithm stdtuple uniform-initialization
add a comment |
Today, I arrived at a situation, where I have a vector of tuples, where the tuples might contain several entries. Now I wanted to convert my vector of tuples to a vector of objects, such that the entries of the tuples will exactly match the uniform initialization of my object.
The following code does the job for me, but it is a bit clumsy. I'm asking myself if it might be possible to derive a generic solution that can construct the Objects if the tuples matches exactly the uniform initialization order of the objects.
This might be a very desirable functionality, when the number of parameters to pass grows.
#include <vector>
#include <tuple>
#include <string>
#include <algorithm>
struct Object
std::string s;
int i;
double d;
;
int main()
std::vector<std::tuple<std::string, int, double>> values = "A",0,0.,"B",1,1. ;
std::vector<Object> objs;
std::transform(values.begin(), values.end(), std::back_inserter(objs), [](auto v)->Object
// This might get tedious to type, if the tuple grows
return std::get<0>(v), std::get<1>(v), std::get<2>(v) ;
// This is my desired behavior, but I don't know what magic_wrapper might be
// return magic_wrapper(v);
);
return EXIT_SUCCESS;
c++ stl stl-algorithm stdtuple uniform-initialization
add a comment |
Today, I arrived at a situation, where I have a vector of tuples, where the tuples might contain several entries. Now I wanted to convert my vector of tuples to a vector of objects, such that the entries of the tuples will exactly match the uniform initialization of my object.
The following code does the job for me, but it is a bit clumsy. I'm asking myself if it might be possible to derive a generic solution that can construct the Objects if the tuples matches exactly the uniform initialization order of the objects.
This might be a very desirable functionality, when the number of parameters to pass grows.
#include <vector>
#include <tuple>
#include <string>
#include <algorithm>
struct Object
std::string s;
int i;
double d;
;
int main()
std::vector<std::tuple<std::string, int, double>> values = "A",0,0.,"B",1,1. ;
std::vector<Object> objs;
std::transform(values.begin(), values.end(), std::back_inserter(objs), [](auto v)->Object
// This might get tedious to type, if the tuple grows
return std::get<0>(v), std::get<1>(v), std::get<2>(v) ;
// This is my desired behavior, but I don't know what magic_wrapper might be
// return magic_wrapper(v);
);
return EXIT_SUCCESS;
c++ stl stl-algorithm stdtuple uniform-initialization
Today, I arrived at a situation, where I have a vector of tuples, where the tuples might contain several entries. Now I wanted to convert my vector of tuples to a vector of objects, such that the entries of the tuples will exactly match the uniform initialization of my object.
The following code does the job for me, but it is a bit clumsy. I'm asking myself if it might be possible to derive a generic solution that can construct the Objects if the tuples matches exactly the uniform initialization order of the objects.
This might be a very desirable functionality, when the number of parameters to pass grows.
#include <vector>
#include <tuple>
#include <string>
#include <algorithm>
struct Object
std::string s;
int i;
double d;
;
int main()
std::vector<std::tuple<std::string, int, double>> values = "A",0,0.,"B",1,1. ;
std::vector<Object> objs;
std::transform(values.begin(), values.end(), std::back_inserter(objs), [](auto v)->Object
// This might get tedious to type, if the tuple grows
return std::get<0>(v), std::get<1>(v), std::get<2>(v) ;
// This is my desired behavior, but I don't know what magic_wrapper might be
// return magic_wrapper(v);
);
return EXIT_SUCCESS;
c++ stl stl-algorithm stdtuple uniform-initialization
c++ stl stl-algorithm stdtuple uniform-initialization
edited Jul 5 at 8:17
Aleph0
asked Jul 5 at 8:09
Aleph0Aleph0
2,15412 silver badges32 bronze badges
2,15412 silver badges32 bronze badges
add a comment |
add a comment |
3 Answers
3
active
oldest
votes
Here is a non-intrusive version (i.e. not touching Object
) that extracts the number of specified data members. Note that this relies on aggregate initialization.
template <class T, class Src, std::size_t... Is>
constexpr auto createAggregateImpl(const Src& src, std::index_sequence<Is...>)
return Tstd::get<Is>(src)...;
template <class T, std::size_t n, class Src>
constexpr auto createAggregate(const Src& src)
return createAggregateImpl<T>(src, std::make_index_sequence<n>);
You invoke it like this:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object return createAggregate<Object, 3>(v); );
Or, without the wrapping lambda:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
createAggregate<Object, 3, decltype(values)::value_type>);
As @Deduplicator pointed out, the above helper templates implement parts of std::apply
, which can be used instead.
template <class T>
auto aggregateInit()
return [](auto&&... args) return Objectstd::forward<decltype(args)>(args)...; ;
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object return std::apply(aggregateInit<Object>(), v); );
Yes, but I need to figure out the best way to pass the 3rd template parameter
– lubgr
Jul 5 at 8:23
@lubgr: That's even more closer to what I desire. Especially, it is a reusable function, that doesn't assume a special kind of Object. Great Solution. Would it be possible to replace thestd::transform
with astd::copy
?
– Aleph0
Jul 5 at 8:23
3
No,std::copy
doesn't work, because there is a transformation happening, you construct one type from another one, which can't be implicit when done with a function (template) exterior to the target type.
– lubgr
Jul 5 at 8:26
Alright. I just because in the solution of @Stack Danny it was possible to replace thestd::transform
with anstd::copy
. But you solution is a complete different story to tell.
– Aleph0
Jul 5 at 8:27
1
Why not usestd::apply()
?
– Deduplicator
Jul 5 at 12:33
|
show 1 more comment
Provide Object
an std::tuple
constructor. You can use std::tie
to assign your members:
template<typename ...Args>
Object(std::tuple<Args...> t)
std::tie(s, i, d) = t;
Now it gets automatically constructed:
std::transform(values.begin(), values.end(), std::back_inserter(objs),
[](auto v) -> Object
return v ;
);
To reduce the amount of copying you might want to replace auto v
with const auto& v
and make the constructor accept a const std::tuple<Args...>& t
.
Also, it's good practise to access the source container via const
iterator:
std::transform(
values.cbegin(), values.cend()
, std::back_inserter(objs), ...
Very cool! Btw. that even makes thestd::transform
astd::copy
.
– Aleph0
Jul 5 at 8:16
Could you explain how this constructor works? And what the template is for ?
– BartekPL
Jul 5 at 8:19
4
@BartekPL this is the typical layout for anstd::tuple
. This template is called a parameter pack.std::tie
constructs a reference tuple which makes an assignement possible.
– Stack Danny
Jul 5 at 8:22
@StackDanny Thanks :)
– BartekPL
Jul 5 at 8:56
add a comment |
Since C++17, you might use std::make_from_tuple:
std::transform(values.begin(),
values.end(),
std::back_inserter(objs),
[](const auto& t)
return std::make_from_tuple<Object>(t);
);
Note: requires appropriated constructor for Object
.
add a comment |
Your Answer
StackExchange.ifUsing("editor", function ()
StackExchange.using("externalEditor", function ()
StackExchange.using("snippets", function ()
StackExchange.snippets.init();
);
);
, "code-snippets");
StackExchange.ready(function()
var channelOptions =
tags: "".split(" "),
id: "1"
;
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function()
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled)
StackExchange.using("snippets", function()
createEditor();
);
else
createEditor();
);
function createEditor()
StackExchange.prepareEditor(
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: true,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: 10,
bindNavPrevention: true,
postfix: "",
imageUploader:
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
,
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
);
);
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56899054%2funiform-initialization-by-tuple%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
3 Answers
3
active
oldest
votes
3 Answers
3
active
oldest
votes
active
oldest
votes
active
oldest
votes
Here is a non-intrusive version (i.e. not touching Object
) that extracts the number of specified data members. Note that this relies on aggregate initialization.
template <class T, class Src, std::size_t... Is>
constexpr auto createAggregateImpl(const Src& src, std::index_sequence<Is...>)
return Tstd::get<Is>(src)...;
template <class T, std::size_t n, class Src>
constexpr auto createAggregate(const Src& src)
return createAggregateImpl<T>(src, std::make_index_sequence<n>);
You invoke it like this:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object return createAggregate<Object, 3>(v); );
Or, without the wrapping lambda:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
createAggregate<Object, 3, decltype(values)::value_type>);
As @Deduplicator pointed out, the above helper templates implement parts of std::apply
, which can be used instead.
template <class T>
auto aggregateInit()
return [](auto&&... args) return Objectstd::forward<decltype(args)>(args)...; ;
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object return std::apply(aggregateInit<Object>(), v); );
Yes, but I need to figure out the best way to pass the 3rd template parameter
– lubgr
Jul 5 at 8:23
@lubgr: That's even more closer to what I desire. Especially, it is a reusable function, that doesn't assume a special kind of Object. Great Solution. Would it be possible to replace thestd::transform
with astd::copy
?
– Aleph0
Jul 5 at 8:23
3
No,std::copy
doesn't work, because there is a transformation happening, you construct one type from another one, which can't be implicit when done with a function (template) exterior to the target type.
– lubgr
Jul 5 at 8:26
Alright. I just because in the solution of @Stack Danny it was possible to replace thestd::transform
with anstd::copy
. But you solution is a complete different story to tell.
– Aleph0
Jul 5 at 8:27
1
Why not usestd::apply()
?
– Deduplicator
Jul 5 at 12:33
|
show 1 more comment
Here is a non-intrusive version (i.e. not touching Object
) that extracts the number of specified data members. Note that this relies on aggregate initialization.
template <class T, class Src, std::size_t... Is>
constexpr auto createAggregateImpl(const Src& src, std::index_sequence<Is...>)
return Tstd::get<Is>(src)...;
template <class T, std::size_t n, class Src>
constexpr auto createAggregate(const Src& src)
return createAggregateImpl<T>(src, std::make_index_sequence<n>);
You invoke it like this:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object return createAggregate<Object, 3>(v); );
Or, without the wrapping lambda:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
createAggregate<Object, 3, decltype(values)::value_type>);
As @Deduplicator pointed out, the above helper templates implement parts of std::apply
, which can be used instead.
template <class T>
auto aggregateInit()
return [](auto&&... args) return Objectstd::forward<decltype(args)>(args)...; ;
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object return std::apply(aggregateInit<Object>(), v); );
Yes, but I need to figure out the best way to pass the 3rd template parameter
– lubgr
Jul 5 at 8:23
@lubgr: That's even more closer to what I desire. Especially, it is a reusable function, that doesn't assume a special kind of Object. Great Solution. Would it be possible to replace thestd::transform
with astd::copy
?
– Aleph0
Jul 5 at 8:23
3
No,std::copy
doesn't work, because there is a transformation happening, you construct one type from another one, which can't be implicit when done with a function (template) exterior to the target type.
– lubgr
Jul 5 at 8:26
Alright. I just because in the solution of @Stack Danny it was possible to replace thestd::transform
with anstd::copy
. But you solution is a complete different story to tell.
– Aleph0
Jul 5 at 8:27
1
Why not usestd::apply()
?
– Deduplicator
Jul 5 at 12:33
|
show 1 more comment
Here is a non-intrusive version (i.e. not touching Object
) that extracts the number of specified data members. Note that this relies on aggregate initialization.
template <class T, class Src, std::size_t... Is>
constexpr auto createAggregateImpl(const Src& src, std::index_sequence<Is...>)
return Tstd::get<Is>(src)...;
template <class T, std::size_t n, class Src>
constexpr auto createAggregate(const Src& src)
return createAggregateImpl<T>(src, std::make_index_sequence<n>);
You invoke it like this:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object return createAggregate<Object, 3>(v); );
Or, without the wrapping lambda:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
createAggregate<Object, 3, decltype(values)::value_type>);
As @Deduplicator pointed out, the above helper templates implement parts of std::apply
, which can be used instead.
template <class T>
auto aggregateInit()
return [](auto&&... args) return Objectstd::forward<decltype(args)>(args)...; ;
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object return std::apply(aggregateInit<Object>(), v); );
Here is a non-intrusive version (i.e. not touching Object
) that extracts the number of specified data members. Note that this relies on aggregate initialization.
template <class T, class Src, std::size_t... Is>
constexpr auto createAggregateImpl(const Src& src, std::index_sequence<Is...>)
return Tstd::get<Is>(src)...;
template <class T, std::size_t n, class Src>
constexpr auto createAggregate(const Src& src)
return createAggregateImpl<T>(src, std::make_index_sequence<n>);
You invoke it like this:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object return createAggregate<Object, 3>(v); );
Or, without the wrapping lambda:
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
createAggregate<Object, 3, decltype(values)::value_type>);
As @Deduplicator pointed out, the above helper templates implement parts of std::apply
, which can be used instead.
template <class T>
auto aggregateInit()
return [](auto&&... args) return Objectstd::forward<decltype(args)>(args)...; ;
std::transform(values.cbegin(), values.cend(), std::back_inserter(objs),
[](const auto& v)->Object return std::apply(aggregateInit<Object>(), v); );
edited Jul 8 at 7:42
answered Jul 5 at 8:19
lubgrlubgr
22.1k3 gold badges31 silver badges74 bronze badges
22.1k3 gold badges31 silver badges74 bronze badges
Yes, but I need to figure out the best way to pass the 3rd template parameter
– lubgr
Jul 5 at 8:23
@lubgr: That's even more closer to what I desire. Especially, it is a reusable function, that doesn't assume a special kind of Object. Great Solution. Would it be possible to replace thestd::transform
with astd::copy
?
– Aleph0
Jul 5 at 8:23
3
No,std::copy
doesn't work, because there is a transformation happening, you construct one type from another one, which can't be implicit when done with a function (template) exterior to the target type.
– lubgr
Jul 5 at 8:26
Alright. I just because in the solution of @Stack Danny it was possible to replace thestd::transform
with anstd::copy
. But you solution is a complete different story to tell.
– Aleph0
Jul 5 at 8:27
1
Why not usestd::apply()
?
– Deduplicator
Jul 5 at 12:33
|
show 1 more comment
Yes, but I need to figure out the best way to pass the 3rd template parameter
– lubgr
Jul 5 at 8:23
@lubgr: That's even more closer to what I desire. Especially, it is a reusable function, that doesn't assume a special kind of Object. Great Solution. Would it be possible to replace thestd::transform
with astd::copy
?
– Aleph0
Jul 5 at 8:23
3
No,std::copy
doesn't work, because there is a transformation happening, you construct one type from another one, which can't be implicit when done with a function (template) exterior to the target type.
– lubgr
Jul 5 at 8:26
Alright. I just because in the solution of @Stack Danny it was possible to replace thestd::transform
with anstd::copy
. But you solution is a complete different story to tell.
– Aleph0
Jul 5 at 8:27
1
Why not usestd::apply()
?
– Deduplicator
Jul 5 at 12:33
Yes, but I need to figure out the best way to pass the 3rd template parameter
– lubgr
Jul 5 at 8:23
Yes, but I need to figure out the best way to pass the 3rd template parameter
– lubgr
Jul 5 at 8:23
@lubgr: That's even more closer to what I desire. Especially, it is a reusable function, that doesn't assume a special kind of Object. Great Solution. Would it be possible to replace the
std::transform
with a std::copy
?– Aleph0
Jul 5 at 8:23
@lubgr: That's even more closer to what I desire. Especially, it is a reusable function, that doesn't assume a special kind of Object. Great Solution. Would it be possible to replace the
std::transform
with a std::copy
?– Aleph0
Jul 5 at 8:23
3
3
No,
std::copy
doesn't work, because there is a transformation happening, you construct one type from another one, which can't be implicit when done with a function (template) exterior to the target type.– lubgr
Jul 5 at 8:26
No,
std::copy
doesn't work, because there is a transformation happening, you construct one type from another one, which can't be implicit when done with a function (template) exterior to the target type.– lubgr
Jul 5 at 8:26
Alright. I just because in the solution of @Stack Danny it was possible to replace the
std::transform
with an std::copy
. But you solution is a complete different story to tell.– Aleph0
Jul 5 at 8:27
Alright. I just because in the solution of @Stack Danny it was possible to replace the
std::transform
with an std::copy
. But you solution is a complete different story to tell.– Aleph0
Jul 5 at 8:27
1
1
Why not use
std::apply()
?– Deduplicator
Jul 5 at 12:33
Why not use
std::apply()
?– Deduplicator
Jul 5 at 12:33
|
show 1 more comment
Provide Object
an std::tuple
constructor. You can use std::tie
to assign your members:
template<typename ...Args>
Object(std::tuple<Args...> t)
std::tie(s, i, d) = t;
Now it gets automatically constructed:
std::transform(values.begin(), values.end(), std::back_inserter(objs),
[](auto v) -> Object
return v ;
);
To reduce the amount of copying you might want to replace auto v
with const auto& v
and make the constructor accept a const std::tuple<Args...>& t
.
Also, it's good practise to access the source container via const
iterator:
std::transform(
values.cbegin(), values.cend()
, std::back_inserter(objs), ...
Very cool! Btw. that even makes thestd::transform
astd::copy
.
– Aleph0
Jul 5 at 8:16
Could you explain how this constructor works? And what the template is for ?
– BartekPL
Jul 5 at 8:19
4
@BartekPL this is the typical layout for anstd::tuple
. This template is called a parameter pack.std::tie
constructs a reference tuple which makes an assignement possible.
– Stack Danny
Jul 5 at 8:22
@StackDanny Thanks :)
– BartekPL
Jul 5 at 8:56
add a comment |
Provide Object
an std::tuple
constructor. You can use std::tie
to assign your members:
template<typename ...Args>
Object(std::tuple<Args...> t)
std::tie(s, i, d) = t;
Now it gets automatically constructed:
std::transform(values.begin(), values.end(), std::back_inserter(objs),
[](auto v) -> Object
return v ;
);
To reduce the amount of copying you might want to replace auto v
with const auto& v
and make the constructor accept a const std::tuple<Args...>& t
.
Also, it's good practise to access the source container via const
iterator:
std::transform(
values.cbegin(), values.cend()
, std::back_inserter(objs), ...
Very cool! Btw. that even makes thestd::transform
astd::copy
.
– Aleph0
Jul 5 at 8:16
Could you explain how this constructor works? And what the template is for ?
– BartekPL
Jul 5 at 8:19
4
@BartekPL this is the typical layout for anstd::tuple
. This template is called a parameter pack.std::tie
constructs a reference tuple which makes an assignement possible.
– Stack Danny
Jul 5 at 8:22
@StackDanny Thanks :)
– BartekPL
Jul 5 at 8:56
add a comment |
Provide Object
an std::tuple
constructor. You can use std::tie
to assign your members:
template<typename ...Args>
Object(std::tuple<Args...> t)
std::tie(s, i, d) = t;
Now it gets automatically constructed:
std::transform(values.begin(), values.end(), std::back_inserter(objs),
[](auto v) -> Object
return v ;
);
To reduce the amount of copying you might want to replace auto v
with const auto& v
and make the constructor accept a const std::tuple<Args...>& t
.
Also, it's good practise to access the source container via const
iterator:
std::transform(
values.cbegin(), values.cend()
, std::back_inserter(objs), ...
Provide Object
an std::tuple
constructor. You can use std::tie
to assign your members:
template<typename ...Args>
Object(std::tuple<Args...> t)
std::tie(s, i, d) = t;
Now it gets automatically constructed:
std::transform(values.begin(), values.end(), std::back_inserter(objs),
[](auto v) -> Object
return v ;
);
To reduce the amount of copying you might want to replace auto v
with const auto& v
and make the constructor accept a const std::tuple<Args...>& t
.
Also, it's good practise to access the source container via const
iterator:
std::transform(
values.cbegin(), values.cend()
, std::back_inserter(objs), ...
edited Jul 5 at 21:43
answered Jul 5 at 8:13
Stack DannyStack Danny
3,36110 silver badges39 bronze badges
3,36110 silver badges39 bronze badges
Very cool! Btw. that even makes thestd::transform
astd::copy
.
– Aleph0
Jul 5 at 8:16
Could you explain how this constructor works? And what the template is for ?
– BartekPL
Jul 5 at 8:19
4
@BartekPL this is the typical layout for anstd::tuple
. This template is called a parameter pack.std::tie
constructs a reference tuple which makes an assignement possible.
– Stack Danny
Jul 5 at 8:22
@StackDanny Thanks :)
– BartekPL
Jul 5 at 8:56
add a comment |
Very cool! Btw. that even makes thestd::transform
astd::copy
.
– Aleph0
Jul 5 at 8:16
Could you explain how this constructor works? And what the template is for ?
– BartekPL
Jul 5 at 8:19
4
@BartekPL this is the typical layout for anstd::tuple
. This template is called a parameter pack.std::tie
constructs a reference tuple which makes an assignement possible.
– Stack Danny
Jul 5 at 8:22
@StackDanny Thanks :)
– BartekPL
Jul 5 at 8:56
Very cool! Btw. that even makes the
std::transform
a std::copy
.– Aleph0
Jul 5 at 8:16
Very cool! Btw. that even makes the
std::transform
a std::copy
.– Aleph0
Jul 5 at 8:16
Could you explain how this constructor works? And what the template is for ?
– BartekPL
Jul 5 at 8:19
Could you explain how this constructor works? And what the template is for ?
– BartekPL
Jul 5 at 8:19
4
4
@BartekPL this is the typical layout for an
std::tuple
. This template is called a parameter pack. std::tie
constructs a reference tuple which makes an assignement possible.– Stack Danny
Jul 5 at 8:22
@BartekPL this is the typical layout for an
std::tuple
. This template is called a parameter pack. std::tie
constructs a reference tuple which makes an assignement possible.– Stack Danny
Jul 5 at 8:22
@StackDanny Thanks :)
– BartekPL
Jul 5 at 8:56
@StackDanny Thanks :)
– BartekPL
Jul 5 at 8:56
add a comment |
Since C++17, you might use std::make_from_tuple:
std::transform(values.begin(),
values.end(),
std::back_inserter(objs),
[](const auto& t)
return std::make_from_tuple<Object>(t);
);
Note: requires appropriated constructor for Object
.
add a comment |
Since C++17, you might use std::make_from_tuple:
std::transform(values.begin(),
values.end(),
std::back_inserter(objs),
[](const auto& t)
return std::make_from_tuple<Object>(t);
);
Note: requires appropriated constructor for Object
.
add a comment |
Since C++17, you might use std::make_from_tuple:
std::transform(values.begin(),
values.end(),
std::back_inserter(objs),
[](const auto& t)
return std::make_from_tuple<Object>(t);
);
Note: requires appropriated constructor for Object
.
Since C++17, you might use std::make_from_tuple:
std::transform(values.begin(),
values.end(),
std::back_inserter(objs),
[](const auto& t)
return std::make_from_tuple<Object>(t);
);
Note: requires appropriated constructor for Object
.
edited Jul 9 at 10:12
answered Jul 5 at 12:06
Jarod42Jarod42
126k12 gold badges109 silver badges198 bronze badges
126k12 gold badges109 silver badges198 bronze badges
add a comment |
add a comment |
Thanks for contributing an answer to Stack Overflow!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2fstackoverflow.com%2fquestions%2f56899054%2funiform-initialization-by-tuple%23new-answer', 'question_page');
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown