Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

make_unique error in compile time [duplicate]

I have just started to learn smart pointers stl::make_unique

Have to change old codes to modern c++

I am getting following error when I compile the below line of code(sample of original code )

#include <memory>
#include <iostream>

using namespace std;
struct Student
{
    int  id;
    float Score;
};
auto main()->int
{
    auto Student1 = make_unique<Student>(1, 5.5);
    //auto Student1 = make_unique<int>(1);  //Works perfectly
    //auto Student2 = unique_ptr<Student>{ new Student{1,22.5} }; //Works 
    cout << "working";
    return 0;
}

1>------ Build started: Project: ConsoleApplication4, Configuration: Debug Win32 ------
1>Source.cpp
1>c:\program files (x86)\microsoft visual studio\2017\enterprise\vc\tools\msvc\14.10.25017\include\memory(2054): error C2661: 'Student::Student': no overloaded function takes 2 arguments
1>c:\users\hsingh\documents\visual studio 2017\projects\consoleapplication4\consoleapplication4\source.cpp(12): note: see reference to function template instantiation 'std::unique_ptr<Student,std::default_delete<_Ty>> std::make_unique<Student,int,double>(int &&,double &&)' being compiled
1>        with
1>        [
1>            _Ty=Student
1>        ]
1>Done building project "ConsoleApplication4.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========

I tried to look into the make_unique implementation looks like it should have worked .Looked in the above site and possible implementation was

// note: this implementation does not disable this overload for array types
template<typename T, typename... Args>
std::unique_ptr<T> make_unique(Args&&... args)
{
    return std::unique_ptr<T>(new T(std::forward<Args>(args)...));
}

so my question is (work around now what i have is to directly use the unique_ptr)

  1. How to make it working using make_unique

  2. What changes I can do to the make_unique implementation in STL so that it works

After few answers Added question 3

3.What is best using make_unique with constructor or just directly using unique_ptr

unique_ptr<Student>{ new Student{1,22.5} }

I am preferring the later as no need to define constructor .Please do suggest

like image 538
Hariom Singh Avatar asked Mar 09 '23 11:03

Hariom Singh


2 Answers

Unfortunately, make_unique does not perform direct list initialization. If you look into it's description here, you will see following statement:

Constructs a non-array type T. The arguments args are passed to the constructor of T. This overload only participates in overload resolution if T is not an array type. The function is equivalent to: unique_ptr(new T(std::forward(args)...))

Your class doesn't have a constructor which accepts two arguments. It is an aggregate, though, and could be constructed using aggregate initialization, as in your second example:

auto* p = new Student{2, 3};

But make_unique is not calling this form, so this is why it fails. There is a suggestion to make it work like that: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4462.html

like image 175
SergeyA Avatar answered Mar 22 '23 22:03

SergeyA


Basically, std::make_unique<T> forwards its arguments to the constructor of type T. But there is no constructor in class Student accepting int and double. You might add one:

struct Student
{
    Student(int id, float Score) : id(id), Score(Score) {}
    int  id;
    float Score;
};

to make the code work.

like image 42
Edgar Rokjān Avatar answered Mar 22 '23 23:03

Edgar Rokjān