Search code examples
c++constructionin-place

In place constrution of member variable via constructor


Take the following class:

template <typename TPayload>
class Message
{
    public:
        Message(const TPayload& payload)
             : m_header(sizeof(TPayload)),
               m_payload(payload) {}

    private:
        const Header   m_header;
        const TPayload m_payload;
};

Whenever I construct a Message I have to create a TPayload (the parameter payload), copy this into m_payload, and then destruct payload. Now consider this can be done 100'000s of times a second, I think this is a wasted effort.

My question is, can I force an inplace construction of m_payload to avoid the tempory payload?

One possible solution I am considering is overloading the construction many times like below but to be honest with all the copying of the multiple argumwents I'm doubting there is much saving.

template <typename TPayload>
class Message
{
    public:
        template <typename A>
        Message(const A& a)
             : m_header(sizeof(TPayload)),
               m_payload(a) {}

        template <typename A, typename B>
        Message(const A& a, const B& b)
             : m_header(sizeof(TPayload)),
               m_payload(a, b) {}

    private:
        const Header   m_header;
        const TPayload m_payload;
};

Solution

  • What you're looking for is forwarding of constructor arguments given to Message to the constructor of Message::m_payload.

    This can be done neatly in C++11 (using variadic templates and std::forward, as used in std::vector<>::emplace_back() and many other functions) or with several overloads in C++03, as you started writing, and as used in boost::make_shared<>

    for example:

    #include <iostream>
    #include <string>
    #include <utility>
    typedef size_t Header;
    template <typename TPayload>
    class Message
    {
        public:
            template <typename ...Args>
            Message(Args&&... args)
                 : m_header(sizeof(TPayload)),
                   m_payload(std::forward<Args>(args)...)
                   {}
            void show_payload() const
            {
                    std::cout << m_payload << '\n';
            }
        private:
            const Header   m_header;
            const TPayload m_payload;
    };
    
    int main()
    {
         Message<std::string> test(10, 'a');
         test.show_payload();
    
         Message<double> test2(3.14);
         test2.show_payload();
    }
    

    test run: https://ideone.com/J1JnZ