Initializer lists and smart pointers

Started by
1 comment, last by Servant of the Lord 9 years, 4 months ago

Hi!

I'm having a problem with some code not working as i whant it so, i've simplified an example:


#include <vector>
#include <initializer_list>
#include <memory>

class Test
{
public:
	typedef std::initializer_list<std::shared_ptr<int>> InitList_t;
	Test( InitList_t init ) :
		m_intVector( init.begin(), init.end() ) {}
	~Test() = default;

private:
	std::vector<std::shared_ptr<int>> m_intVector;
};

int main()
{
	// Works!
	Test t1( { 
		std::make_shared<int>( 1 ), 
		std::make_shared<int>( 2 ),
		std::make_shared<int>( 3 )
	} );

	// Does not work!
	auto t2 = std::make_unique<Test>( { 
		std::make_shared<int>( 1 ), 
		std::make_shared<int>( 2 ),
		std::make_shared<int>( 3 )
	} );

	// Works!
	auto t3 = std::make_unique<Test>( Test::InitList_t { 
		std::make_shared<int>( 1 ), 
		std::make_shared<int>( 2 ),
		std::make_shared<int>( 3 )
	} );

	return 0;
}

What i don't understand is why i have to tdefine the initializer list type when using unique_ptr, but not when not using them.

Can someone help me understand this please?

Advertisement

The second option doesn't work because std::make_unique is a function template and template argument deduction (unlike auto) can't deduce that { ... } is an std::initializer_list.

Basically the C++11 standard doesn't allow it. More info here

This should work as well:


                                      vvvv
    auto t3 = std::make_unique<Test>( Test {
        std::make_shared<int>( 1 ),
        std::make_shared<int>( 2 ),
        std::make_shared<int>( 3 )
    } );

Creates an unnamed 'Test' rvalue, moves it into the unique pointer using Test's move-constructor.

This topic is closed to new replies.

Advertisement