Initialize static std::map with non copyable value in a uniformed inline initialization
I'd like to initialize a static std::map
where the value is not copyable. I'll call my class ValueClass. ValueClass has an std::unique_ptr
as private member and I even ensure that ValueClass is not copyable by extending non_copyable
that looks like the following:
class non_copyable {
public:
non_copyable() = default;
protected:
virtual ~non_copyable() = default;
private:
non_copyable(const non_copyable&) = delete;
non_copyable& operator=(const non_copyable&) = delete;
};
Now I'm trying to define a std::map using my class as value:
static std::map<int, ValueClass> value_classes = {
{0, ValueClass()},
{1, ValueClass() }
};
I get compilation error as initializer_list
tries to copy this class.
I've tried to write my own make_map
function whole this weekend during many hours to enable initialization without copying but I've failed. I've tried this, that and other but none of them compile with Visual Studio 15.9.4.
How can I initialize static std::map where copy is not forced, and the initialization is uniformed in one function, using Visual Studio compiler?
EDIT:
Here is the simplified version of the real life scenario where I'm trying to get this working (forgive me for lack of naming convention and inconsistency for cases):
#include <iostream>
#include <map>
class non_copyable {
public:
non_copyable() = default;
protected:
virtual ~non_copyable() = default;
private:
non_copyable(const non_copyable&) = delete;
non_copyable& operator=(const non_copyable&) = delete;
};
class InnerValueClass : public non_copyable
{
public:
InnerValueClass(const int inner_number) : inner_number_(inner_number) { }
private:
int inner_number_;
};
class ValueClass : public non_copyable
{
public:
ValueClass(const int number1) : number1_(number1) { }
ValueClass(const bool condition) : condition_(condition), inner_value_(
std::make_unique<InnerValueClass>(5)) { }
private:
int number1_{};
bool condition_{};
std::unique_ptr<InnerValueClass> inner_value_{};
};
/* Inline initialization of std::map copies, this is for initialization of non-copy types*/
template <typename TKey, typename TNonCopyableValue>
class make_map_by_moving
{
typedef std::map<TKey, TNonCopyableValue> map_type;
map_type map_;
public:
make_map_by_moving(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(key, std::move(val));
}
make_map_by_moving<TKey, TNonCopyableValue>& operator()(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(key, std::move(val));
return *this;
}
operator const map_type&()
{
return map_;
}
};
static std::map<int, ValueClass> map =
make_map_by_moving<int, ValueClass>
(1, ValueClass(5))
(2, ValueClass(true));
/* It goes on like this for hundreds of lines, so I really appreciate any
solution that leave me with a clean initialization rather than calling
functions on std::map */
int main() { }
Duplicate edit: The solution provided in that question does not work the class structure I have. I'm also looking for a solution to fix make_map_by_moving
function in other words an inline initialization, the answer provided there is an imperative solution with function calls.
c++ c++17 static-initialization noncopyable
add a comment |
I'd like to initialize a static std::map
where the value is not copyable. I'll call my class ValueClass. ValueClass has an std::unique_ptr
as private member and I even ensure that ValueClass is not copyable by extending non_copyable
that looks like the following:
class non_copyable {
public:
non_copyable() = default;
protected:
virtual ~non_copyable() = default;
private:
non_copyable(const non_copyable&) = delete;
non_copyable& operator=(const non_copyable&) = delete;
};
Now I'm trying to define a std::map using my class as value:
static std::map<int, ValueClass> value_classes = {
{0, ValueClass()},
{1, ValueClass() }
};
I get compilation error as initializer_list
tries to copy this class.
I've tried to write my own make_map
function whole this weekend during many hours to enable initialization without copying but I've failed. I've tried this, that and other but none of them compile with Visual Studio 15.9.4.
How can I initialize static std::map where copy is not forced, and the initialization is uniformed in one function, using Visual Studio compiler?
EDIT:
Here is the simplified version of the real life scenario where I'm trying to get this working (forgive me for lack of naming convention and inconsistency for cases):
#include <iostream>
#include <map>
class non_copyable {
public:
non_copyable() = default;
protected:
virtual ~non_copyable() = default;
private:
non_copyable(const non_copyable&) = delete;
non_copyable& operator=(const non_copyable&) = delete;
};
class InnerValueClass : public non_copyable
{
public:
InnerValueClass(const int inner_number) : inner_number_(inner_number) { }
private:
int inner_number_;
};
class ValueClass : public non_copyable
{
public:
ValueClass(const int number1) : number1_(number1) { }
ValueClass(const bool condition) : condition_(condition), inner_value_(
std::make_unique<InnerValueClass>(5)) { }
private:
int number1_{};
bool condition_{};
std::unique_ptr<InnerValueClass> inner_value_{};
};
/* Inline initialization of std::map copies, this is for initialization of non-copy types*/
template <typename TKey, typename TNonCopyableValue>
class make_map_by_moving
{
typedef std::map<TKey, TNonCopyableValue> map_type;
map_type map_;
public:
make_map_by_moving(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(key, std::move(val));
}
make_map_by_moving<TKey, TNonCopyableValue>& operator()(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(key, std::move(val));
return *this;
}
operator const map_type&()
{
return map_;
}
};
static std::map<int, ValueClass> map =
make_map_by_moving<int, ValueClass>
(1, ValueClass(5))
(2, ValueClass(true));
/* It goes on like this for hundreds of lines, so I really appreciate any
solution that leave me with a clean initialization rather than calling
functions on std::map */
int main() { }
Duplicate edit: The solution provided in that question does not work the class structure I have. I'm also looking for a solution to fix make_map_by_moving
function in other words an inline initialization, the answer provided there is an imperative solution with function calls.
c++ c++17 static-initialization noncopyable
Is this map meant to be editable at runtime after the first initialization? I do recall a proposal (or implementation even) for a global const structure that offers natural initialization and map-like performance
– M.M
Dec 16 at 23:09
I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
– Francis Cugler
Dec 16 at 23:12
add a comment |
I'd like to initialize a static std::map
where the value is not copyable. I'll call my class ValueClass. ValueClass has an std::unique_ptr
as private member and I even ensure that ValueClass is not copyable by extending non_copyable
that looks like the following:
class non_copyable {
public:
non_copyable() = default;
protected:
virtual ~non_copyable() = default;
private:
non_copyable(const non_copyable&) = delete;
non_copyable& operator=(const non_copyable&) = delete;
};
Now I'm trying to define a std::map using my class as value:
static std::map<int, ValueClass> value_classes = {
{0, ValueClass()},
{1, ValueClass() }
};
I get compilation error as initializer_list
tries to copy this class.
I've tried to write my own make_map
function whole this weekend during many hours to enable initialization without copying but I've failed. I've tried this, that and other but none of them compile with Visual Studio 15.9.4.
How can I initialize static std::map where copy is not forced, and the initialization is uniformed in one function, using Visual Studio compiler?
EDIT:
Here is the simplified version of the real life scenario where I'm trying to get this working (forgive me for lack of naming convention and inconsistency for cases):
#include <iostream>
#include <map>
class non_copyable {
public:
non_copyable() = default;
protected:
virtual ~non_copyable() = default;
private:
non_copyable(const non_copyable&) = delete;
non_copyable& operator=(const non_copyable&) = delete;
};
class InnerValueClass : public non_copyable
{
public:
InnerValueClass(const int inner_number) : inner_number_(inner_number) { }
private:
int inner_number_;
};
class ValueClass : public non_copyable
{
public:
ValueClass(const int number1) : number1_(number1) { }
ValueClass(const bool condition) : condition_(condition), inner_value_(
std::make_unique<InnerValueClass>(5)) { }
private:
int number1_{};
bool condition_{};
std::unique_ptr<InnerValueClass> inner_value_{};
};
/* Inline initialization of std::map copies, this is for initialization of non-copy types*/
template <typename TKey, typename TNonCopyableValue>
class make_map_by_moving
{
typedef std::map<TKey, TNonCopyableValue> map_type;
map_type map_;
public:
make_map_by_moving(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(key, std::move(val));
}
make_map_by_moving<TKey, TNonCopyableValue>& operator()(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(key, std::move(val));
return *this;
}
operator const map_type&()
{
return map_;
}
};
static std::map<int, ValueClass> map =
make_map_by_moving<int, ValueClass>
(1, ValueClass(5))
(2, ValueClass(true));
/* It goes on like this for hundreds of lines, so I really appreciate any
solution that leave me with a clean initialization rather than calling
functions on std::map */
int main() { }
Duplicate edit: The solution provided in that question does not work the class structure I have. I'm also looking for a solution to fix make_map_by_moving
function in other words an inline initialization, the answer provided there is an imperative solution with function calls.
c++ c++17 static-initialization noncopyable
I'd like to initialize a static std::map
where the value is not copyable. I'll call my class ValueClass. ValueClass has an std::unique_ptr
as private member and I even ensure that ValueClass is not copyable by extending non_copyable
that looks like the following:
class non_copyable {
public:
non_copyable() = default;
protected:
virtual ~non_copyable() = default;
private:
non_copyable(const non_copyable&) = delete;
non_copyable& operator=(const non_copyable&) = delete;
};
Now I'm trying to define a std::map using my class as value:
static std::map<int, ValueClass> value_classes = {
{0, ValueClass()},
{1, ValueClass() }
};
I get compilation error as initializer_list
tries to copy this class.
I've tried to write my own make_map
function whole this weekend during many hours to enable initialization without copying but I've failed. I've tried this, that and other but none of them compile with Visual Studio 15.9.4.
How can I initialize static std::map where copy is not forced, and the initialization is uniformed in one function, using Visual Studio compiler?
EDIT:
Here is the simplified version of the real life scenario where I'm trying to get this working (forgive me for lack of naming convention and inconsistency for cases):
#include <iostream>
#include <map>
class non_copyable {
public:
non_copyable() = default;
protected:
virtual ~non_copyable() = default;
private:
non_copyable(const non_copyable&) = delete;
non_copyable& operator=(const non_copyable&) = delete;
};
class InnerValueClass : public non_copyable
{
public:
InnerValueClass(const int inner_number) : inner_number_(inner_number) { }
private:
int inner_number_;
};
class ValueClass : public non_copyable
{
public:
ValueClass(const int number1) : number1_(number1) { }
ValueClass(const bool condition) : condition_(condition), inner_value_(
std::make_unique<InnerValueClass>(5)) { }
private:
int number1_{};
bool condition_{};
std::unique_ptr<InnerValueClass> inner_value_{};
};
/* Inline initialization of std::map copies, this is for initialization of non-copy types*/
template <typename TKey, typename TNonCopyableValue>
class make_map_by_moving
{
typedef std::map<TKey, TNonCopyableValue> map_type;
map_type map_;
public:
make_map_by_moving(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(key, std::move(val));
}
make_map_by_moving<TKey, TNonCopyableValue>& operator()(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(key, std::move(val));
return *this;
}
operator const map_type&()
{
return map_;
}
};
static std::map<int, ValueClass> map =
make_map_by_moving<int, ValueClass>
(1, ValueClass(5))
(2, ValueClass(true));
/* It goes on like this for hundreds of lines, so I really appreciate any
solution that leave me with a clean initialization rather than calling
functions on std::map */
int main() { }
Duplicate edit: The solution provided in that question does not work the class structure I have. I'm also looking for a solution to fix make_map_by_moving
function in other words an inline initialization, the answer provided there is an imperative solution with function calls.
c++ c++17 static-initialization noncopyable
c++ c++17 static-initialization noncopyable
edited 13 hours ago
asked Dec 16 at 21:35
U. Bulle
180111
180111
Is this map meant to be editable at runtime after the first initialization? I do recall a proposal (or implementation even) for a global const structure that offers natural initialization and map-like performance
– M.M
Dec 16 at 23:09
I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
– Francis Cugler
Dec 16 at 23:12
add a comment |
Is this map meant to be editable at runtime after the first initialization? I do recall a proposal (or implementation even) for a global const structure that offers natural initialization and map-like performance
– M.M
Dec 16 at 23:09
I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
– Francis Cugler
Dec 16 at 23:12
Is this map meant to be editable at runtime after the first initialization? I do recall a proposal (or implementation even) for a global const structure that offers natural initialization and map-like performance
– M.M
Dec 16 at 23:09
Is this map meant to be editable at runtime after the first initialization? I do recall a proposal (or implementation even) for a global const structure that offers natural initialization and map-like performance
– M.M
Dec 16 at 23:09
I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
– Francis Cugler
Dec 16 at 23:12
I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
– Francis Cugler
Dec 16 at 23:12
add a comment |
3 Answers
3
active
oldest
votes
You cannot do this directly, because initializer_list
has const
backing for all of its elements - and they have to be copied from the initializer list into the container. That, obviously, requires copying. There's no way to emplace from an initializer list unfortunately.
In C++17, thanks to guaranteed copy elision, you can do this:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.emplace(std::piecewise_construct, std::tuple(0), std::tuple());
m.emplace(std::piecewise_construct, std::tuple(1), std::tuple());
return m;
}
std::map<int, non_copyable> value_classes = get();
This code performs no copies on non_copyable
. We emplace construct inside of the map
, and then beacuse get()
is a prvalue, there is no copy/move from get()
into value_classes
. The m
within get()
is the object value_classes
.
A slightly sneaker approach would be to abuse try_emplace()
for this:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.try_emplace(0);
m.try_emplace(1);
return m;
}
try_emplace()
takes the key type by itself (so you can just pass an int
) and then the arguments for the value for emplacing separately, which makes for a much less verbose way of accomplishing this.
Another way is to simply callm[0]; m[1];
. It will emplace default-constructed objects. See en.cppreference.com/w/cpp/container/map/operator_at.
– tmlen
Dec 16 at 22:11
Whytry_emplace
instead of simple oldemplace
?
– R2RT
Dec 16 at 22:11
Thank you for the answer! I realized that I was not clear in the question, I'm sorry for that. I don't want to leave the values to be defined later on, I'd like to define the values as well. I've updated my question with the code showing the real scenario I'm having.
– U. Bulle
Dec 16 at 22:13
@U.Bulle Well, I don't know how you expect yourValueClass(int, const InnerValueClass&)
constructor to work given thatInnerValueClass
isn't copyable - but besides that, this answer provides a path to provide arbitrary constructor arguments just fine.
– Barry
Dec 16 at 22:40
add a comment |
I think you need to create the object with insert_or_assign
in a function and then return it:
std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.insert_or_assign(std::make_pair(0, ValueClass());
return value_classes;
}
And your initialization becomes:
std::map<int, ValueClass> value_classes = populate();
But then, this class has a virtual destructor, which means that you want actually may actually be a std::map<int, std::unique_ptr<ValueClass>>
and not a map of actual objects (not sure what these objects are going to be used for?).
Edit after the question edit:
In this case, Barrys suggestion is the one to follow, using
emplace`:
std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.emplace(1, 5);
return value_classes;
}
Also include functional
.
Thank you for very fast and informative answer. I've updated my question with the code showing the real life application.insert_or_assign
did not help it to compile either.
– U. Bulle
Dec 16 at 22:12
Wow, that's a completely different beast...
– Matthieu Brucher
Dec 16 at 22:18
I getC2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments
with your integration of Barry`s suggestion :(
– U. Bulle
Dec 16 at 22:34
Seems like a bug, works with clang :/
– Matthieu Brucher
Dec 16 at 22:38
I would suggest you change your special class to remove the usage of emplace. Barry's code or mine work for your case, just create an actual function. Also, you have a big bug in your code, as the reference_wrapper points to a temporary that is destroyed.
– Matthieu Brucher
Dec 16 at 22:40
|
show 2 more comments
You simply can not use initializer_list
to move
an object from a non-copyable
object.
Your class deletes the copy constructor
& assignment operator
. When you try to initialize your map
or any other container
with an initializer_list
the initializer_list
strictly forces you to reference an LValue
and forbids RValue
move or forward semantics.
Here is a very nice blog article that explains all of the details: knatten.org as well as a similar Q/A found here.
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%2f53806687%2finitialize-static-stdmap-with-non-copyable-value-in-a-uniformed-inline-initial%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
You cannot do this directly, because initializer_list
has const
backing for all of its elements - and they have to be copied from the initializer list into the container. That, obviously, requires copying. There's no way to emplace from an initializer list unfortunately.
In C++17, thanks to guaranteed copy elision, you can do this:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.emplace(std::piecewise_construct, std::tuple(0), std::tuple());
m.emplace(std::piecewise_construct, std::tuple(1), std::tuple());
return m;
}
std::map<int, non_copyable> value_classes = get();
This code performs no copies on non_copyable
. We emplace construct inside of the map
, and then beacuse get()
is a prvalue, there is no copy/move from get()
into value_classes
. The m
within get()
is the object value_classes
.
A slightly sneaker approach would be to abuse try_emplace()
for this:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.try_emplace(0);
m.try_emplace(1);
return m;
}
try_emplace()
takes the key type by itself (so you can just pass an int
) and then the arguments for the value for emplacing separately, which makes for a much less verbose way of accomplishing this.
Another way is to simply callm[0]; m[1];
. It will emplace default-constructed objects. See en.cppreference.com/w/cpp/container/map/operator_at.
– tmlen
Dec 16 at 22:11
Whytry_emplace
instead of simple oldemplace
?
– R2RT
Dec 16 at 22:11
Thank you for the answer! I realized that I was not clear in the question, I'm sorry for that. I don't want to leave the values to be defined later on, I'd like to define the values as well. I've updated my question with the code showing the real scenario I'm having.
– U. Bulle
Dec 16 at 22:13
@U.Bulle Well, I don't know how you expect yourValueClass(int, const InnerValueClass&)
constructor to work given thatInnerValueClass
isn't copyable - but besides that, this answer provides a path to provide arbitrary constructor arguments just fine.
– Barry
Dec 16 at 22:40
add a comment |
You cannot do this directly, because initializer_list
has const
backing for all of its elements - and they have to be copied from the initializer list into the container. That, obviously, requires copying. There's no way to emplace from an initializer list unfortunately.
In C++17, thanks to guaranteed copy elision, you can do this:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.emplace(std::piecewise_construct, std::tuple(0), std::tuple());
m.emplace(std::piecewise_construct, std::tuple(1), std::tuple());
return m;
}
std::map<int, non_copyable> value_classes = get();
This code performs no copies on non_copyable
. We emplace construct inside of the map
, and then beacuse get()
is a prvalue, there is no copy/move from get()
into value_classes
. The m
within get()
is the object value_classes
.
A slightly sneaker approach would be to abuse try_emplace()
for this:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.try_emplace(0);
m.try_emplace(1);
return m;
}
try_emplace()
takes the key type by itself (so you can just pass an int
) and then the arguments for the value for emplacing separately, which makes for a much less verbose way of accomplishing this.
Another way is to simply callm[0]; m[1];
. It will emplace default-constructed objects. See en.cppreference.com/w/cpp/container/map/operator_at.
– tmlen
Dec 16 at 22:11
Whytry_emplace
instead of simple oldemplace
?
– R2RT
Dec 16 at 22:11
Thank you for the answer! I realized that I was not clear in the question, I'm sorry for that. I don't want to leave the values to be defined later on, I'd like to define the values as well. I've updated my question with the code showing the real scenario I'm having.
– U. Bulle
Dec 16 at 22:13
@U.Bulle Well, I don't know how you expect yourValueClass(int, const InnerValueClass&)
constructor to work given thatInnerValueClass
isn't copyable - but besides that, this answer provides a path to provide arbitrary constructor arguments just fine.
– Barry
Dec 16 at 22:40
add a comment |
You cannot do this directly, because initializer_list
has const
backing for all of its elements - and they have to be copied from the initializer list into the container. That, obviously, requires copying. There's no way to emplace from an initializer list unfortunately.
In C++17, thanks to guaranteed copy elision, you can do this:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.emplace(std::piecewise_construct, std::tuple(0), std::tuple());
m.emplace(std::piecewise_construct, std::tuple(1), std::tuple());
return m;
}
std::map<int, non_copyable> value_classes = get();
This code performs no copies on non_copyable
. We emplace construct inside of the map
, and then beacuse get()
is a prvalue, there is no copy/move from get()
into value_classes
. The m
within get()
is the object value_classes
.
A slightly sneaker approach would be to abuse try_emplace()
for this:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.try_emplace(0);
m.try_emplace(1);
return m;
}
try_emplace()
takes the key type by itself (so you can just pass an int
) and then the arguments for the value for emplacing separately, which makes for a much less verbose way of accomplishing this.
You cannot do this directly, because initializer_list
has const
backing for all of its elements - and they have to be copied from the initializer list into the container. That, obviously, requires copying. There's no way to emplace from an initializer list unfortunately.
In C++17, thanks to guaranteed copy elision, you can do this:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.emplace(std::piecewise_construct, std::tuple(0), std::tuple());
m.emplace(std::piecewise_construct, std::tuple(1), std::tuple());
return m;
}
std::map<int, non_copyable> value_classes = get();
This code performs no copies on non_copyable
. We emplace construct inside of the map
, and then beacuse get()
is a prvalue, there is no copy/move from get()
into value_classes
. The m
within get()
is the object value_classes
.
A slightly sneaker approach would be to abuse try_emplace()
for this:
std::map<int, non_copyable> get() {
std::map<int, non_copyable> m;
m.try_emplace(0);
m.try_emplace(1);
return m;
}
try_emplace()
takes the key type by itself (so you can just pass an int
) and then the arguments for the value for emplacing separately, which makes for a much less verbose way of accomplishing this.
answered Dec 16 at 21:44
Barry
176k18301557
176k18301557
Another way is to simply callm[0]; m[1];
. It will emplace default-constructed objects. See en.cppreference.com/w/cpp/container/map/operator_at.
– tmlen
Dec 16 at 22:11
Whytry_emplace
instead of simple oldemplace
?
– R2RT
Dec 16 at 22:11
Thank you for the answer! I realized that I was not clear in the question, I'm sorry for that. I don't want to leave the values to be defined later on, I'd like to define the values as well. I've updated my question with the code showing the real scenario I'm having.
– U. Bulle
Dec 16 at 22:13
@U.Bulle Well, I don't know how you expect yourValueClass(int, const InnerValueClass&)
constructor to work given thatInnerValueClass
isn't copyable - but besides that, this answer provides a path to provide arbitrary constructor arguments just fine.
– Barry
Dec 16 at 22:40
add a comment |
Another way is to simply callm[0]; m[1];
. It will emplace default-constructed objects. See en.cppreference.com/w/cpp/container/map/operator_at.
– tmlen
Dec 16 at 22:11
Whytry_emplace
instead of simple oldemplace
?
– R2RT
Dec 16 at 22:11
Thank you for the answer! I realized that I was not clear in the question, I'm sorry for that. I don't want to leave the values to be defined later on, I'd like to define the values as well. I've updated my question with the code showing the real scenario I'm having.
– U. Bulle
Dec 16 at 22:13
@U.Bulle Well, I don't know how you expect yourValueClass(int, const InnerValueClass&)
constructor to work given thatInnerValueClass
isn't copyable - but besides that, this answer provides a path to provide arbitrary constructor arguments just fine.
– Barry
Dec 16 at 22:40
Another way is to simply call
m[0]; m[1];
. It will emplace default-constructed objects. See en.cppreference.com/w/cpp/container/map/operator_at.– tmlen
Dec 16 at 22:11
Another way is to simply call
m[0]; m[1];
. It will emplace default-constructed objects. See en.cppreference.com/w/cpp/container/map/operator_at.– tmlen
Dec 16 at 22:11
Why
try_emplace
instead of simple old emplace
?– R2RT
Dec 16 at 22:11
Why
try_emplace
instead of simple old emplace
?– R2RT
Dec 16 at 22:11
Thank you for the answer! I realized that I was not clear in the question, I'm sorry for that. I don't want to leave the values to be defined later on, I'd like to define the values as well. I've updated my question with the code showing the real scenario I'm having.
– U. Bulle
Dec 16 at 22:13
Thank you for the answer! I realized that I was not clear in the question, I'm sorry for that. I don't want to leave the values to be defined later on, I'd like to define the values as well. I've updated my question with the code showing the real scenario I'm having.
– U. Bulle
Dec 16 at 22:13
@U.Bulle Well, I don't know how you expect your
ValueClass(int, const InnerValueClass&)
constructor to work given that InnerValueClass
isn't copyable - but besides that, this answer provides a path to provide arbitrary constructor arguments just fine.– Barry
Dec 16 at 22:40
@U.Bulle Well, I don't know how you expect your
ValueClass(int, const InnerValueClass&)
constructor to work given that InnerValueClass
isn't copyable - but besides that, this answer provides a path to provide arbitrary constructor arguments just fine.– Barry
Dec 16 at 22:40
add a comment |
I think you need to create the object with insert_or_assign
in a function and then return it:
std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.insert_or_assign(std::make_pair(0, ValueClass());
return value_classes;
}
And your initialization becomes:
std::map<int, ValueClass> value_classes = populate();
But then, this class has a virtual destructor, which means that you want actually may actually be a std::map<int, std::unique_ptr<ValueClass>>
and not a map of actual objects (not sure what these objects are going to be used for?).
Edit after the question edit:
In this case, Barrys suggestion is the one to follow, using
emplace`:
std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.emplace(1, 5);
return value_classes;
}
Also include functional
.
Thank you for very fast and informative answer. I've updated my question with the code showing the real life application.insert_or_assign
did not help it to compile either.
– U. Bulle
Dec 16 at 22:12
Wow, that's a completely different beast...
– Matthieu Brucher
Dec 16 at 22:18
I getC2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments
with your integration of Barry`s suggestion :(
– U. Bulle
Dec 16 at 22:34
Seems like a bug, works with clang :/
– Matthieu Brucher
Dec 16 at 22:38
I would suggest you change your special class to remove the usage of emplace. Barry's code or mine work for your case, just create an actual function. Also, you have a big bug in your code, as the reference_wrapper points to a temporary that is destroyed.
– Matthieu Brucher
Dec 16 at 22:40
|
show 2 more comments
I think you need to create the object with insert_or_assign
in a function and then return it:
std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.insert_or_assign(std::make_pair(0, ValueClass());
return value_classes;
}
And your initialization becomes:
std::map<int, ValueClass> value_classes = populate();
But then, this class has a virtual destructor, which means that you want actually may actually be a std::map<int, std::unique_ptr<ValueClass>>
and not a map of actual objects (not sure what these objects are going to be used for?).
Edit after the question edit:
In this case, Barrys suggestion is the one to follow, using
emplace`:
std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.emplace(1, 5);
return value_classes;
}
Also include functional
.
Thank you for very fast and informative answer. I've updated my question with the code showing the real life application.insert_or_assign
did not help it to compile either.
– U. Bulle
Dec 16 at 22:12
Wow, that's a completely different beast...
– Matthieu Brucher
Dec 16 at 22:18
I getC2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments
with your integration of Barry`s suggestion :(
– U. Bulle
Dec 16 at 22:34
Seems like a bug, works with clang :/
– Matthieu Brucher
Dec 16 at 22:38
I would suggest you change your special class to remove the usage of emplace. Barry's code or mine work for your case, just create an actual function. Also, you have a big bug in your code, as the reference_wrapper points to a temporary that is destroyed.
– Matthieu Brucher
Dec 16 at 22:40
|
show 2 more comments
I think you need to create the object with insert_or_assign
in a function and then return it:
std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.insert_or_assign(std::make_pair(0, ValueClass());
return value_classes;
}
And your initialization becomes:
std::map<int, ValueClass> value_classes = populate();
But then, this class has a virtual destructor, which means that you want actually may actually be a std::map<int, std::unique_ptr<ValueClass>>
and not a map of actual objects (not sure what these objects are going to be used for?).
Edit after the question edit:
In this case, Barrys suggestion is the one to follow, using
emplace`:
std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.emplace(1, 5);
return value_classes;
}
Also include functional
.
I think you need to create the object with insert_or_assign
in a function and then return it:
std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.insert_or_assign(std::make_pair(0, ValueClass());
return value_classes;
}
And your initialization becomes:
std::map<int, ValueClass> value_classes = populate();
But then, this class has a virtual destructor, which means that you want actually may actually be a std::map<int, std::unique_ptr<ValueClass>>
and not a map of actual objects (not sure what these objects are going to be used for?).
Edit after the question edit:
In this case, Barrys suggestion is the one to follow, using
emplace`:
std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.emplace(1, 5);
return value_classes;
}
Also include functional
.
edited Dec 16 at 23:03
answered Dec 16 at 21:42
Matthieu Brucher
11.5k22137
11.5k22137
Thank you for very fast and informative answer. I've updated my question with the code showing the real life application.insert_or_assign
did not help it to compile either.
– U. Bulle
Dec 16 at 22:12
Wow, that's a completely different beast...
– Matthieu Brucher
Dec 16 at 22:18
I getC2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments
with your integration of Barry`s suggestion :(
– U. Bulle
Dec 16 at 22:34
Seems like a bug, works with clang :/
– Matthieu Brucher
Dec 16 at 22:38
I would suggest you change your special class to remove the usage of emplace. Barry's code or mine work for your case, just create an actual function. Also, you have a big bug in your code, as the reference_wrapper points to a temporary that is destroyed.
– Matthieu Brucher
Dec 16 at 22:40
|
show 2 more comments
Thank you for very fast and informative answer. I've updated my question with the code showing the real life application.insert_or_assign
did not help it to compile either.
– U. Bulle
Dec 16 at 22:12
Wow, that's a completely different beast...
– Matthieu Brucher
Dec 16 at 22:18
I getC2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments
with your integration of Barry`s suggestion :(
– U. Bulle
Dec 16 at 22:34
Seems like a bug, works with clang :/
– Matthieu Brucher
Dec 16 at 22:38
I would suggest you change your special class to remove the usage of emplace. Barry's code or mine work for your case, just create an actual function. Also, you have a big bug in your code, as the reference_wrapper points to a temporary that is destroyed.
– Matthieu Brucher
Dec 16 at 22:40
Thank you for very fast and informative answer. I've updated my question with the code showing the real life application.
insert_or_assign
did not help it to compile either.– U. Bulle
Dec 16 at 22:12
Thank you for very fast and informative answer. I've updated my question with the code showing the real life application.
insert_or_assign
did not help it to compile either.– U. Bulle
Dec 16 at 22:12
Wow, that's a completely different beast...
– Matthieu Brucher
Dec 16 at 22:18
Wow, that's a completely different beast...
– Matthieu Brucher
Dec 16 at 22:18
I get
C2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments
with your integration of Barry`s suggestion :(– U. Bulle
Dec 16 at 22:34
I get
C2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments
with your integration of Barry`s suggestion :(– U. Bulle
Dec 16 at 22:34
Seems like a bug, works with clang :/
– Matthieu Brucher
Dec 16 at 22:38
Seems like a bug, works with clang :/
– Matthieu Brucher
Dec 16 at 22:38
I would suggest you change your special class to remove the usage of emplace. Barry's code or mine work for your case, just create an actual function. Also, you have a big bug in your code, as the reference_wrapper points to a temporary that is destroyed.
– Matthieu Brucher
Dec 16 at 22:40
I would suggest you change your special class to remove the usage of emplace. Barry's code or mine work for your case, just create an actual function. Also, you have a big bug in your code, as the reference_wrapper points to a temporary that is destroyed.
– Matthieu Brucher
Dec 16 at 22:40
|
show 2 more comments
You simply can not use initializer_list
to move
an object from a non-copyable
object.
Your class deletes the copy constructor
& assignment operator
. When you try to initialize your map
or any other container
with an initializer_list
the initializer_list
strictly forces you to reference an LValue
and forbids RValue
move or forward semantics.
Here is a very nice blog article that explains all of the details: knatten.org as well as a similar Q/A found here.
add a comment |
You simply can not use initializer_list
to move
an object from a non-copyable
object.
Your class deletes the copy constructor
& assignment operator
. When you try to initialize your map
or any other container
with an initializer_list
the initializer_list
strictly forces you to reference an LValue
and forbids RValue
move or forward semantics.
Here is a very nice blog article that explains all of the details: knatten.org as well as a similar Q/A found here.
add a comment |
You simply can not use initializer_list
to move
an object from a non-copyable
object.
Your class deletes the copy constructor
& assignment operator
. When you try to initialize your map
or any other container
with an initializer_list
the initializer_list
strictly forces you to reference an LValue
and forbids RValue
move or forward semantics.
Here is a very nice blog article that explains all of the details: knatten.org as well as a similar Q/A found here.
You simply can not use initializer_list
to move
an object from a non-copyable
object.
Your class deletes the copy constructor
& assignment operator
. When you try to initialize your map
or any other container
with an initializer_list
the initializer_list
strictly forces you to reference an LValue
and forbids RValue
move or forward semantics.
Here is a very nice blog article that explains all of the details: knatten.org as well as a similar Q/A found here.
answered Dec 16 at 23:21
Francis Cugler
4,38211227
4,38211227
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.
Some of your past answers have not been well-received, and you're in danger of being blocked from answering.
Please pay close attention to the following guidance:
- 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%2f53806687%2finitialize-static-stdmap-with-non-copyable-value-in-a-uniformed-inline-initial%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
Is this map meant to be editable at runtime after the first initialization? I do recall a proposal (or implementation even) for a global const structure that offers natural initialization and map-like performance
– M.M
Dec 16 at 23:09
I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
– Francis Cugler
Dec 16 at 23:12