I'm trying to create a pair of int and a unique_ptr. How should I use make_pair to create this ?
#include <string>
#include <memory>
#include <algorithm>
int main()
{
std::unique_ptr<int> p = std::make_unique<int>(0);
std::pair<int, std::unique_ptr<int>> pr = std::make_pair((int)0, p);
}
I run into the following issue,
Error C2440 '<function-style-cast>': cannot convert from 'initializer list' to '_Mypair' templpairuniqueptr c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.15.26726\include\utility 405
I could not understand why this happens. I'm on MSVC.
You cannot copy unique pointers. After all, the copy would not be unique. Move instead:
auto pr = std::make_pair(
0, std::make_unique<int>(0)
);
You can move from lvalues as well, if you need to, by converting the lvalue to an rvalue with std::move:
auto pr = std::make_pair(
0, std::move(p)
);
Related
I am trying to create a function func that returns an std::tuple of an std::unique_ptr<A> and a double. However, when I try to create the tuple I receive errors. The code follows:
#include <tuple>
#include <memory>
class A {
public:
A() : data (3){}
private:
double data;
};
std::tuple<std::unique_ptr<A>, double> func(double num) {
std::unique_ptr<A> a = std::make_unique<A>();
std::tuple<std::unique_ptr<A>, double> temp = std::make_tuple(a, num); // ERROR MESSAGE C
return temp;
}
int main() {
return 0;
}
This code produces the following 4 errors in Visual Studio.
Error message A:
tuple(827,18): error C2440: '<function-style-cast>': cannot convert from 'initializer list' to '_Ttype'
Error message B:
tuple(825,83): message : No constructor could take the source type, or constructor overload resolution was ambiguous
Error message C:
Source.cpp(14): message : see reference to function template instantiation 'std::tuple<std::unique_ptr<A,std::default_delete<A>>,double> std::make_tuple<std::unique_ptr<A,std::default_delete<A>>&,double&>(std::unique_ptr<A,std::default_delete<A>> &,double &)' being compiled
Error message D:
tuple(827,12): error C2064: term does not evaluate to a function taking 2 arguments
First, what is the cause of this error? Second, is the A associated with a being placed on the heap?
A std::unique_ptr is not copyable. You are attempting to copy a std::unique_ptr to the tuple, and that will not work. The compiler error message is kind of cryptic, IMO, but that is basically what seems to be the problem.
However, a std::unique_ptr is moveable, thus you can use std::move:
std::tuple<std::unique_ptr<A>, double> temp = std::make_tuple(std::move(a), num);
I'm trying to store the address returned by the algorithm remove function in C++ in a variable, but have failed to find one. I've tried int* and char*. Both threw errors.
Using Visual Studio CL, the error is:
error C2440: '=': cannot convert from '_FwdIt' to 'int *'
Using MinGW, the error is:
cannot convert '__gnu_cxx::__normal_iterator<char*, std::__cxx11::basic_string<char> >' to 'int*' in assignment
How should I store such an address?
The code I'm trying:
#include <stdio.h>
#include <iostream>
#include <string>
#include <algorithm>
using namespace std;
int main (void) {
string line ("This is an example sentence.");
int* newEOL;
newEOL = remove(line.begin(), line.end(), ' ');
printf("%p\n", newEOL);
}
Why do you think it's a pointer?
As evidenced here: https://en.cppreference.com/w/cpp/algorithm/remove
it's an iterator, which can be implemented as a pointer, but doesn't have to.
You can use the auto keyword if you don't want to specify the type explicitly.
I was looking at an answer to another question. However I can't figure out, based on that example, why can't I bind a value of some local variable with MSVC 2015 compiler? It just throws an error while gcc 5.3 compiles it fine on msys2/mingw64. I mean like in
#include <iostream>
#include <functional>
#include <vector>
int add(int a, int b) { return a + b; }
using bound_add_t = decltype(std::bind(add, std::placeholders::_1, int()));
int main() {
std::vector<bound_add_t> vec;
int y = 2;
vec.emplace_back(add,std::placeholders::_1, y); // <- this causes the problem
vec.emplace_back(add,std::placeholders::_1, 2);
vec.emplace_back(add,std::placeholders::_1, 3);
for (auto &b : vec)
std::cout << b(5) << std::endl;
return 0;
}
Severity Code Description Project File Line Suppression State
Error C2664 'std::_Binder &,int>::_Binder(std::_Binder &,int> &&)': cannot convert argument 3 from 'int' to 'int &&' C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xmemory0 655
Is it a known issue tracked somewhere? I'm not even sure what is the underlying problem here. Is there a workaround?
In my use case, I'm missing one argument that becomes available later, so I'd want to have a vector with a wrapped function ready just like in that example.
Update
Is it a C++14 thing? I was poking around on http://ideone.com/Zi1Yht . While there is no MSVC, only compiler marked as C++14 was able to compile it.
Update 2
I tried
std::vector<std::function<int(int)> > vec;
vec.emplace_back(add, std::placeholders::_1, y);
if that was implied, I get
Severity Code Description Project File Line Suppression State
Error C2664 'std::function::function(std::function &&)': cannot convert argument 1 from 'int (__cdecl &)(int,int)' to 'std::allocator_arg_t' C:\Program Files (x86)\Microsoft Visual Studio 14.0\VC\include\xmemory0 655
MSVC is in its right in rejecting this code. int() is a temporary and therefore corresponding Args&&... parameter is deduced as int&&. So the constructor of the result type of bind can take int&& as the last parameter, and y is not an rvalue so compilation fails.
This is not a bug in other compilers, because the result of bind is unspecified.
If you don't want to fall back to std::function you can enforce the type of the last parameter to be const int&:
using bound_add_t = decltype(std::bind(add, std::placeholders::_1, std::declval<const int&>()));
The return type of std::bind is unspecified.
The required constructor is the copy constructor or the move constructor.
Construct it from the arguments (function, placeholders, ...) you give is unspecified and may work for specific implementation but is not portable.
As a workaround, you may do
std::vector<std::function<int(int)> > vec;
int y = 2;
vec.push_back(std::bind(add, std::placeholders::_1, y));
vec.push_back(std::bind(add, std::placeholders::_1, 2));
vec.push_back(std::bind(add, std::placeholders::_1, 3));
I'm using Visual Studio 2005 and Boost 1.37. I also tested this same code on Visual Studio 2012 Express Desktop and Boost 1.50 without success.
I want to use a Boost.Lambda by accessing a custom subscript operator on my type. It also happens when using with std::array, so I'll illustrate the problem with the std::array type:
#include <vector>
#include <array>
#include <algorithm>
int main() {
std::vector<std::array<int, 3>> arrays;
arrays.push_back(make_array(1, 2, 3));
arrays.push_back(make_array(5, 5, 6));
std::for_each(arrays.begin(), arrays.end(), (_1[0])); //This line fails!
return 0;
}
The errors are:
error C2664: 'boost::lambda::detail::unspecified::unspecified(const boost::lambda::detail::unspecified &)' : cannot convert parameter 1 from 'int' to 'const boost::lambda::detail::unspecified &'
Reason: cannot convert from 'int' to 'const boost::lambda::detail::unspecified'
No constructor could take the source type, or constructor overload resolution was ambiguous
... ad infinitum...
I found this page: Extending return type deduction system
But I couldn't successfully implement it.
Does anyone know what can be done here?
Tying to compile the following program with Visual Studio 10, I get lot of compile errors:
#include "stdafx.h"
#include <tuple>
#include <string>
#include <map>
#include <iostream>
int _tmain(int argc, _TCHAR* argv[])
{
typedef std::tuple<std::string, std::string> key_t;
typedef std::map<key_t, std::string> map_t;
map_t the_map;
auto k = std::make_tuple("one", "two");
the_map[k] = "the value";
auto q = std::make_tuple("one", "two");
auto i = the_map.find(q);
std::cout << i->second << std::endl;
return 0;
}
Error 1 error C2664: 'std::basic_string<_Elem,_Traits,_Ax>::basic_string(const std::basic_string<_Elem,_Traits,_Ax> &)' : cannot convert parameter 1 from 'const key_t' to 'const std::basic_string<_Elem,_Traits,_Ax> &' c:\program files (x86)\microsoft visual studio 10.0\vc\include\tuple 127 1 tuple
Coming from the line:
std::cout << i->second << std::endl;
Strange thing is, as least from my point of view, if I change these lines:
auto k = std::make_tuple("one", "two");
the_map[k] = "the value";
to
the_map[std::make_tuple("one", "two")] = "p";
the program compiles. So my question is of course why? I guess it has something to do with make_tuple and move semantics - but I do not understand what..
Apparently the error comes in fact from the line the_map[k] = "the value";
When you use the [] operator on a map, the library tries to create a std::pair<Key,Value> object. In your case, this becomes std::pair<std::tuple<std::string,std::string>,std::string>.
However if you use an intermediate variable k, the constructor of std::pair which is called is: (copy-pasted from the standard lib)
_Pair_base(const _Ty1x& _Val1, _Ty2x&& _Val2)
: first(_Val1), second(_STD move(_Val2))
{ // construct from specified values
}
This constructor is trying to make a copy of your key_t. Unfortunatly, the tuple implementation of MSVC++ is bugged at the moment and the copy fails to compile (see also this: C++0x : are tuples of tuples allowed?)
I can diagnosize more, because this implementation is not only bugged but also very complicated.
Boost's tuples should work but don't have an < operator, so you can't use them.
The "best" solution for the moment is to write the_map.insert(std::make_pair(k, "the value"));
This looks like a bug in VS10, for some reason it's trying to cast the key type to the value type.
This simplified version also fails.
typedef std::map<std::tuple<int, int>, int> map_t;
map_t the_map;
map_t::key_type k = std::make_tuple(1,2);
the_map[k] = 3;
Produces the following:
error C2440: 'initializing' : cannot convert from 'const std::tr1::tuple<_Arg0,_Arg1>' to 'int'