make_unique error in compile time [duplicate] - c++

This question already has answers here:
using c++ aggregate initialization in std::make_shared
(3 answers)
Closed 5 years ago.
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)
How to make it working using make_unique
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

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

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.

Related

Template Alias, Variable Template, and auto type deduction failing to deduce template argument

While working on my class declaration I'm having some confusion on how to use alias templates and template variables within in a non class template while trying to use auto type deduction.
Signal.h
#ifndef SIGNAL_H
#define SIGNAL_H
#include <cstdint>
template<typename T>
using TimeSignal = T;
using DiscreteTime = TimeSignal<std::uint8_t>;
using ContinuousTime = TimeSignal<double>;
class Signal {
private:
template<typename T>
static TimeSignal<T> time_;
double voltage_;
double current_;
public:
template<typename T>
explicit Signal( TimeSignal<T> time, double voltage = 0, double current = 0 ) :
voltage_{voltage}, current_{current}
{ time_ = time; }
double sampleVoltage() { return voltage_; }
double sampleCurrent() { return current_; }
template<typename T>
static auto atTime() { return time_; }
};
#endif // SIGNAL_H
And I would be using it like this:
#include <iostream>
#include "Signal.h"
int main() {
DiscreteTime t1{ 5 };
ContinuousTime t2{ 7.5 };
Signal s1{ t1, 3.5, 0.05 );
Signal s2{ t2, 4.3, 0.09 );
auto time1 = s1.atTime();
auto time2 = s2.atTime();
return 0;
}
I don't want to template this class, so I was thinking about having an internal variable template. Outside of the class I was trying to use a template alias to have the different "TimeSignals" be descriptive as a "DiscreteTime" is typically and integral type and a ContinousTime is a floating point or over the set of Real numbers. I was however templating the constructor of this class that takes in the TimeSignal type and wanted the class to deduce the or to auto resolve it's internal variable template to that type depending which of the two types were passed in. Finally I was trying to use auto type deduction to return that type.
I don't know if its the syntax or the usage but this has me stumped. I'm not sure how to get this to a working compile state.
This is the current compiler errors that Visual Studio 2017 is giving me.
1>------ Build started: Project: Circuit Maker Simulator, Configuration: Debug x64 ------
1>main.cpp
1>c:\...\main.cpp(15): error C2672: 'Signal::atTime': no matching overloaded function found
1>c:\...\main.cpp(15): error C2783: 'auto Signal::atTime(void)': could not deduce template argument for 'T'
1>c:\...\Signal.h(64): note: see declaration of 'Signal::atTime'
1>c:\...\main.cpp(24): error C2672: 'Signal::atTime': no matching overloaded function found
1>c:\...\main.cpp(24): error C2783: 'auto Signal::atTime(void)': could not deduce template argument for 'T'
1>c:\...\Signal.h(64): note: see declaration of 'Signal::atTime'
1>Done building project "Circuit Maker Simulator.vcxproj" -- FAILED.
The compiler error's obvious to what they are saying, but it's like they are screaming or yelling at me without any help, assistance or suggestions on how to fix or resolve this...
Edit
User rafix07 helped me quite a bit with his answer and it was helpful. I was missing a couple of things, two of them I may have eventually caught onto if I kept staring at it long enough and that was the use of the variable templates within the class needing it's template argument or parameter. The other was using the scope resolution operator in the main function to call the static function. I could of found them given some time.
The one issue that had me stumbling in circles was the fact that I had to explicitly instantiate the function template of the type I want when calling it. This is the one that would of had me pulling out my hair for ours...
After adjusting the code according to the link in his answer I'm now able to compile, however I am now getting linker errors for unresolved external symbols and it has to do with the template variables. Which shouldn't be a problem, just need to define it within a cpp file to resolve static variables.
First of all, atTime is static method so only way to call it is to use scope resolution operator ::. atTime takes no arguments, so T cannot be deduced, and you need to put type in template arguments list explicitly:
auto time1 = Signal::atTime<DiscreteTime>();
auto time2 = Signal::atTime<ContinuousTime>();
In ctor of Signal and atTime function you have to specify T for which variable template is accessed:
template<typename T>
explicit Signal( TimeSignal<T> time, double voltage = 0, double current = 0 ) :
voltage_{voltage}, current_{current}
{ time_<T> = time; }
Full working code is here.

Dispatch template <auto>

I try to dispatch between two functions using if constexpr. The dispatcher function should accept for example std::size_t and an arbitrary class type.
It works if I just call it with a scalar type, but if I try to pass a class type it triggers a compile error which is not really helpful to me (please see below).
Please have a look at my current approach:
template <auto Other>
constexpr auto mul() const {
if constexpr (std::is_scalar_v<decltype(Other)>)
return mul_with_scalar<Other>();
else
return mul_with_matrix<Other>();
}
template <size_t Scalar>
constexpr auto mul_with_scalar() const {
return apply([](size_t v, auto) { return v * Scalar; },
std::make_index_sequence<Size>{});
}
template <class Other>
constexpr auto mul_with_matrix() const {
return size_t{0}; // implement me
}
note: candidate: template<auto Other> constexpr auto matrix<Rows, Cols, Vals>::mul() const [with auto Other = Other; long unsigned int Rows = 3; long unsigned int Cols = 3; long unsigned int ...Vals = {}]
constexpr auto mul() const {
^~~
./constexpresian/matrix.hpp:81:18: note: template argument deduction/substitution failed:
I wan't that the function mul can handle non-type and type parameters.
That is not possible in C++. A template parameter can be a type or a value (or a template), but it cannot be both. template<auto Name> makes Name a value template parameter, the type of whose value will be deduced at the time the value is passed.
But since it is a compile-time value, you can wrap its value in a type. For integer types, std::integer_constant will work. For future C++ revisions that allow other kinds of value parameters, you'll have to use a more generic wrapper.
There is one question I have, you can refer to my comment below your post that pertains to the term Size.
I tried your code above as is even with Size the way it is to see the compiler errors and this is coming from Visual Studio 2017 v4.6.0105 c++17 on Win 7 x64 Home Premium under x86 Debug on an Intel Quad Core Extreme.
1>------ Build started: Project: StackOverflow, Configuration: Debug Win32 ------
1>Learner.cpp
1>c:\users\skilz80\documents\visual studio 2017\projects\stackoverflow\stackoverflow\learner.h(75): error C3533: a parameter cannot have a type that contains 'auto'
1>c:\users\skilz80\documents\visual studio 2017\projects\stackoverflow\stackoverflow\learner.h(75): error C2270: 'mul': modifiers not allowed on nonmember functions
1>c:\users\skilz80\documents\visual studio 2017\projects\stackoverflow\stackoverflow\learner.h(83): error C2270: 'mul_with_scalar': modifiers not allowed on nonmember functions
1>c:\users\skilz80\documents\visual studio 2017\projects\stackoverflow\stackoverflow\learner.h(89): error C2270: 'mul_with_matrix': modifiers not allowed on nonmember functions
1>Done building project "StackOverflow.vcxproj" -- FAILED.
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
Maybe this interpretation of these compiler errors might help you.
Here are some links that might help concerning auto and template parameters:
StackOverflow : Advantages of auto in template parameters in C++17
open-std.org : Declaring non-type template arguments with auto
www.bfilipek.com : C++17 in details: Templates

Workaround for VS 2013 SFINAE deficiencies

I'm trying to fix up a library (entityx) that does not currently compile on Windows using VS 2013. It compiles fine on Linux with gcc and also on Windows with MinGW.
It seems the problem is with SFINAE - I guess VS 2013 doesn't properly ignore substitution failures for templates.
There is a report of this issue on Microsoft Connect, here.
Before I dive into entityx, there is a sample of the problem (taken from the report at Microsoft Connect):
#include <vector>
#include <future>
using namespace std;
typedef int async_io_op;
struct Foo
{
//! Invoke the specified callable when the supplied operation completes
template<class R> inline std::pair < std::vector < future < R >> , std::vector < async_io_op >> call(const std::vector<async_io_op> &ops, const std::vector < std::function < R() >> &callables);
//! Invoke the specified callable when the supplied operation completes
template<class R> std::pair < std::vector < future < R >> , std::vector < async_io_op >> call(const std::vector < std::function < R() >> &callables) { return call(std::vector<async_io_op>(), callables); }
//! Invoke the specified callable when the supplied operation completes
template<class R> inline std::pair<future<R>, async_io_op> call(const async_io_op &req, std::function<R()> callback);
//! Invoke the specified callable when the supplied operation completes
template<class C, class... Args> inline std::pair<future<typename std::result_of<C(Args...)>::type>, async_io_op> call(const async_io_op &req, C callback, Args... args);
};
int main(void)
{
Foo foo;
std::vector<async_io_op> ops;
std::vector < std::function < int() >> callables;
foo.call(ops, std::move(callables));
return 0;
}
I get the following error when attempting to compile this:
error C2064: term does not evaluate to a function taking 0 arguments
c:\program files (x86)\microsoft visual studio 12.0\vc\include\xrefwrap 58
Apparently, we can use std::enable_if to work around this problem. However, I can't figure out how.
Does anyone know how I can fix this compile error?
Edit: Full output from VS 2013:
1>------ Build started: Project: VS2013_SFINAE_Failure, Configuration: Debug Win32 ------
1> test_case.cpp
1>c:\program files (x86)\microsoft visual studio 12.0\vc\include\xrefwrap(58): error C2064: term does not evaluate to a function taking 0 arguments
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xrefwrap(118) : see reference to class template instantiation 'std::_Result_of<_Fty,>' being compiled
1> with
1> [
1> _Fty=std::vector<std::function<int (void)>,std::allocator<std::function<int (void)>>>
1> ]
1> c:\users\jarrett\downloads\vs2013_sfinae_failure\vs2013_sfinae_failure\test_case.cpp(25) : see reference to class template instantiation 'std::result_of<std::vector<std::function<int (void)>,std::allocator<_Ty>> (void)>' being compiled
1> with
1> [
1> _Ty=std::function<int (void)>
1> ]
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
VS2013 compiles the code if you replace std::result_of with its decltype + std::declval equivalent. So change the last Foo::call() definition to
template<class C, class... Args>
inline pair<future<decltype(declval<C>()(declval<Args>()...))>, async_io_op>
call(const async_io_op& req, C callback, Args... args);
If I understand the error correctly, it's related to the defect described here, but then it's surprising that both GCC and clang manage to compile the result_of code without errors.

Pointer to member, within class

I am trying create a typedef for a template that needs a pointer to member, from within a class. The best way to describe it is to show the minimal sample code:
template<typename T, int T::*MV>
struct Bar
{
const int &value(const T &t) const
{
return (t.*MV);
}
};
struct Foo
{
int baz;
typedef Bar<Foo, &Foo::baz> GetBaz; // Compiler error
};
typedef Bar<Foo, &Foo::baz> GetFooBaz; // Compiles just fine
int main(int argc, char* argv[])
{
Foo f = { 42 };
Foo::GetBaz b; // Fails to compile
GetFooBaz b2; // Fine
int val = b.value(f); // Fails to compile because of above
int val2 = b2.value(f); // Fine
}
I am not necessarily dead-set on getting access to a member pointer in this way, I would be fine just knowing the offset to the variable and having the Bar::value function perform trickery.
As a last resort, I suppose I could use a traits class since the would move the definition outside of the class, but I would prefer to be able to declare the typedef near the variable being used.
And, to answer the "why would you want to do that" question, this is all for an IoC container that closely represents the way MEF (C# works).
The specific compiler I am using is VC12, but it would be nice if VC11 supported it as well.
Thanks
EDIT:
Here are the error messages
1>------ Build started: Project: MemVarBug, Configuration: Debug Win32 ------
1> MemVarBug.cpp
1>memvarbug.cpp(20): error C2327: 'Foo::baz' : is not a type name, static, or enumerator
1>memvarbug.cpp(20): error C2065: 'baz' : undeclared identifier
1>memvarbug.cpp(20): error C2975: 'MV' : invalid template argument for 'Bar', expected compile-time constant expression
1> memvarbug.cpp(7) : see declaration of 'MV'
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
you can do the following trick:
declare baz to be int[1];
array of size one, in this case calling baz will return the pointer and calling *baz will return the value.

C++ Garbage collection, templates and operator overriding - can't understand why it throws an error

I am trying to compile a file which defines a garbage collection template and several supporting classes with use of operator overloading. I've tried to run this through MSVC++ 2008, and the compile stops at this particular class:
// (The collector defines gc_object_generic_base which
// inherits from gc_object_generic_base and optionally adds
// collector-specific properties.)
template<class garbage_collector>
class gc_object_base : public garbage_collector::gc_object_collector_base {
public:
gc_object_base() {
garbage_collector::constructing_gc_object_base(this);
}
static void* operator new(size_t sz,
block_construction_locker_base* lock = block_construction_locker<garbage_collector>().get_this())
{
return garbage_collector::allocate(sz, lock);
}
static void operator delete(void* p, block_construction_locker_base* lock) {
return garbage_collector::deallocate(p);
}
static void operator delete(void* p) {
return garbage_collector::deallocate(p);
}
private:
// TODO: are arrays worth implementing?
static void* operator new[](size_t sz) {
assert(0);
return 0;
}
};
Truncated output for brevity's sake:
2>------ Build started: Project: Test, Configuration: Debug Win32 ------
2>Compiling...
2>FlashTest.cc
2>C:\test\gameswf\base\tu_gc.h(133) : error C2059: syntax error : 'string'
2> C:\test\gameswf\base\tu_gc.h(151) : see reference to class template instantiation 'tu_gc::gc_object_base' being compiled
2>C:\test\gameswf\base\tu_gc.h(135) : error C2091: function returns function
2>C:\test\gameswf\base\tu_gc.h(135) : error C2802: static member 'operator new' has no formal parameters
2>C:\test\gameswf\base\tu_gc.h(135) : error C2333: 'tu_gc::gc_object_base::operator new' : error in function declaration; skipping function body
Any ideas on where I should start looking at?
I just had the same pattern of errors in a different project. It seems to happen when someone has done this somewhere:
#define new new(someArgs, someMoreArgs, etc)
It's targeted at simple 'new' expressions, but it breaks down if anyone tries to declare any more 'operator new' thingies.
In the opening lines
template<class garbage_collector>
class gc_object_base : public garbage_collector::gc_object_collector_base {
garbage_collector appears twice here, once as the template parameter and another as an outer-class to gc_object_collector_base, but as it is a template parameter does it not require "typename" here thus:
template<class garbage_collector>
class gc_object_base : public typename garbage_collector::gc_object_collector_base {
There is no mention of string in your code, that I can see. But I would start by ensuring that you first #include <string> before your class delcaration, and then make sure you use std::string as your declarator, rather than just string.