Initialize static std::map with non copyable value in a uniformed initialization











up vote
6
down vote

favorite
1












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 <optional>
#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 int number1, InnerValueClass&& inner_value) : number1_(number1), inner_value_(std::make_unique<InnerValueClass>(5)) { }
private:
int number1_;
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(std::make_pair(key, std::forward<TNonCopyableValue>(val)));
}
make_map_by_moving<TKey, TNonCopyableValue>& operator()(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(std::make_pair(key, std::forward<TNonCopyableValue>(val)));
return *this;
}
operator const map_type&()
{
return map_;
}
};

static std::map<int, ValueClass> map =
make_map_by_moving(1, ValueClass(5))
(2, ValueClass(5, InnerValueClass(3)));
/* 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()
{

}









share|improve this question
























  • 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
    6 hours ago










  • I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
    – Francis Cugler
    6 hours ago















up vote
6
down vote

favorite
1












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 <optional>
#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 int number1, InnerValueClass&& inner_value) : number1_(number1), inner_value_(std::make_unique<InnerValueClass>(5)) { }
private:
int number1_;
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(std::make_pair(key, std::forward<TNonCopyableValue>(val)));
}
make_map_by_moving<TKey, TNonCopyableValue>& operator()(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(std::make_pair(key, std::forward<TNonCopyableValue>(val)));
return *this;
}
operator const map_type&()
{
return map_;
}
};

static std::map<int, ValueClass> map =
make_map_by_moving(1, ValueClass(5))
(2, ValueClass(5, InnerValueClass(3)));
/* 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()
{

}









share|improve this question
























  • 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
    6 hours ago










  • I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
    – Francis Cugler
    6 hours ago













up vote
6
down vote

favorite
1









up vote
6
down vote

favorite
1






1





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 <optional>
#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 int number1, InnerValueClass&& inner_value) : number1_(number1), inner_value_(std::make_unique<InnerValueClass>(5)) { }
private:
int number1_;
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(std::make_pair(key, std::forward<TNonCopyableValue>(val)));
}
make_map_by_moving<TKey, TNonCopyableValue>& operator()(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(std::make_pair(key, std::forward<TNonCopyableValue>(val)));
return *this;
}
operator const map_type&()
{
return map_;
}
};

static std::map<int, ValueClass> map =
make_map_by_moving(1, ValueClass(5))
(2, ValueClass(5, InnerValueClass(3)));
/* 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()
{

}









share|improve this question















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 <optional>
#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 int number1, InnerValueClass&& inner_value) : number1_(number1), inner_value_(std::make_unique<InnerValueClass>(5)) { }
private:
int number1_;
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(std::make_pair(key, std::forward<TNonCopyableValue>(val)));
}
make_map_by_moving<TKey, TNonCopyableValue>& operator()(const TKey& key, TNonCopyableValue&& val)
{
map_.emplace(std::make_pair(key, std::forward<TNonCopyableValue>(val)));
return *this;
}
operator const map_type&()
{
return map_;
}
};

static std::map<int, ValueClass> map =
make_map_by_moving(1, ValueClass(5))
(2, ValueClass(5, InnerValueClass(3)));
/* 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()
{

}






c++ c++17 static-initialization noncopyable






share|improve this question















share|improve this question













share|improve this question




share|improve this question








edited 5 hours ago

























asked 7 hours ago









U. Bulle

170110




170110












  • 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
    6 hours ago










  • I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
    – Francis Cugler
    6 hours ago


















  • 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
    6 hours ago










  • I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
    – Francis Cugler
    6 hours ago
















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
6 hours ago




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
6 hours ago












I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
– Francis Cugler
6 hours ago




I found this link: blog.knatten.org/2018/10/05/… that may give you some insight!
– Francis Cugler
6 hours ago












3 Answers
3






active

oldest

votes

















up vote
6
down vote













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.






share|improve this answer





















  • 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
    7 hours ago












  • Why try_emplace instead of simple old emplace?
    – R2RT
    7 hours ago










  • 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
    7 hours ago










  • @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
    6 hours ago


















up vote
3
down vote













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, usingemplace`:



std::map<int, ValueClass> populate()
{
std::map<int, ValueClass> value_classes;
value_classes.emplace(1, 5);
return value_classes;
}


Also include functional.






share|improve this answer























  • 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
    7 hours ago










  • Wow, that's a completely different beast...
    – Matthieu Brucher
    7 hours ago










  • I get C2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments with your integration of Barry`s suggestion :(
    – U. Bulle
    6 hours ago










  • Seems like a bug, works with clang :/
    – Matthieu Brucher
    6 hours ago










  • 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
    6 hours ago


















up vote
2
down vote













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.






share|improve this answer





















    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',
    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
    });


    }
    });














    draft saved

    draft discarded


















    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-initialization%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








    up vote
    6
    down vote













    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.






    share|improve this answer





















    • 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
      7 hours ago












    • Why try_emplace instead of simple old emplace?
      – R2RT
      7 hours ago










    • 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
      7 hours ago










    • @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
      6 hours ago















    up vote
    6
    down vote













    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.






    share|improve this answer





















    • 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
      7 hours ago












    • Why try_emplace instead of simple old emplace?
      – R2RT
      7 hours ago










    • 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
      7 hours ago










    • @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
      6 hours ago













    up vote
    6
    down vote










    up vote
    6
    down vote









    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.






    share|improve this answer












    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.







    share|improve this answer












    share|improve this answer



    share|improve this answer










    answered 7 hours ago









    Barry

    176k18299555




    176k18299555












    • 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
      7 hours ago












    • Why try_emplace instead of simple old emplace?
      – R2RT
      7 hours ago










    • 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
      7 hours ago










    • @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
      6 hours ago


















    • 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
      7 hours ago












    • Why try_emplace instead of simple old emplace?
      – R2RT
      7 hours ago










    • 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
      7 hours ago










    • @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
      6 hours ago
















    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
    7 hours ago






    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
    7 hours ago














    Why try_emplace instead of simple old emplace?
    – R2RT
    7 hours ago




    Why try_emplace instead of simple old emplace?
    – R2RT
    7 hours ago












    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
    7 hours ago




    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
    7 hours ago












    @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
    6 hours ago




    @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
    6 hours ago












    up vote
    3
    down vote













    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, usingemplace`:



    std::map<int, ValueClass> populate()
    {
    std::map<int, ValueClass> value_classes;
    value_classes.emplace(1, 5);
    return value_classes;
    }


    Also include functional.






    share|improve this answer























    • 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
      7 hours ago










    • Wow, that's a completely different beast...
      – Matthieu Brucher
      7 hours ago










    • I get C2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments with your integration of Barry`s suggestion :(
      – U. Bulle
      6 hours ago










    • Seems like a bug, works with clang :/
      – Matthieu Brucher
      6 hours ago










    • 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
      6 hours ago















    up vote
    3
    down vote













    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, usingemplace`:



    std::map<int, ValueClass> populate()
    {
    std::map<int, ValueClass> value_classes;
    value_classes.emplace(1, 5);
    return value_classes;
    }


    Also include functional.






    share|improve this answer























    • 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
      7 hours ago










    • Wow, that's a completely different beast...
      – Matthieu Brucher
      7 hours ago










    • I get C2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments with your integration of Barry`s suggestion :(
      – U. Bulle
      6 hours ago










    • Seems like a bug, works with clang :/
      – Matthieu Brucher
      6 hours ago










    • 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
      6 hours ago













    up vote
    3
    down vote










    up vote
    3
    down vote









    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, usingemplace`:



    std::map<int, ValueClass> populate()
    {
    std::map<int, ValueClass> value_classes;
    value_classes.emplace(1, 5);
    return value_classes;
    }


    Also include functional.






    share|improve this answer














    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, usingemplace`:



    std::map<int, ValueClass> populate()
    {
    std::map<int, ValueClass> value_classes;
    value_classes.emplace(1, 5);
    return value_classes;
    }


    Also include functional.







    share|improve this answer














    share|improve this answer



    share|improve this answer








    edited 6 hours ago

























    answered 7 hours ago









    Matthieu Brucher

    10.8k21935




    10.8k21935












    • 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
      7 hours ago










    • Wow, that's a completely different beast...
      – Matthieu Brucher
      7 hours ago










    • I get C2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments with your integration of Barry`s suggestion :(
      – U. Bulle
      6 hours ago










    • Seems like a bug, works with clang :/
      – Matthieu Brucher
      6 hours ago










    • 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
      6 hours ago


















    • 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
      7 hours ago










    • Wow, that's a completely different beast...
      – Matthieu Brucher
      7 hours ago










    • I get C2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments with your integration of Barry`s suggestion :(
      – U. Bulle
      6 hours ago










    • Seems like a bug, works with clang :/
      – Matthieu Brucher
      6 hours ago










    • 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
      6 hours ago
















    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
    7 hours ago




    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
    7 hours ago












    Wow, that's a completely different beast...
    – Matthieu Brucher
    7 hours ago




    Wow, that's a completely different beast...
    – Matthieu Brucher
    7 hours ago












    I get C2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments with your integration of Barry`s suggestion :(
    – U. Bulle
    6 hours ago




    I get C2660 'std::pair<const _Kty,_Ty>::pair': function does not take 2 arguments with your integration of Barry`s suggestion :(
    – U. Bulle
    6 hours ago












    Seems like a bug, works with clang :/
    – Matthieu Brucher
    6 hours ago




    Seems like a bug, works with clang :/
    – Matthieu Brucher
    6 hours ago












    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
    6 hours ago




    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
    6 hours ago










    up vote
    2
    down vote













    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.






    share|improve this answer

























      up vote
      2
      down vote













      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.






      share|improve this answer























        up vote
        2
        down vote










        up vote
        2
        down vote









        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.






        share|improve this answer












        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.







        share|improve this answer












        share|improve this answer



        share|improve this answer










        answered 5 hours ago









        Francis Cugler

        4,32411227




        4,32411227






























            draft saved

            draft discarded




















































            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.




            draft saved


            draft discarded














            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-initialization%23new-answer', 'question_page');
            }
            );

            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







            Popular posts from this blog

            flock() on closed filehandle LOCK_FILE at /usr/bin/apt-mirror

            Mangá

            Eduardo VII do Reino Unido