std::packaged_task bug in Visual Studio? - c++

I found out that a std::packaged_task couldn't be pushed into a std::vector if the parameter type returns void in Visual Studio (2012, 2013, Nov 2013 CTP). For example,
typedef std::packaged_task<void()> packaged_task;
std::vector<packaged_task> tasks;
packaged_task package;
tasks.push_back(std::move(package));
The error messages are:
error C2182: '_Get_value' : illegal use of type 'void'
error C2182: '_Val' : illegal use of type 'void'
error C2182: '_Val' : illegal use of type 'void'
error C2512: 'std::_Promise<int>' : no appropriate default constructor available
error C2665: 'std::forward' : none of the 2 overloads could convert all the argument types
I think this is bug because this code snippet works if
the return type is not void,
it is compiled in XCode.
Are there solutions or other options in Visual Studio? I know that boost can be used to replace this.

I can reproduce this with a simple auto m = std::move(package);.
int main()
{
typedef std::packaged_task<void()> packagedtask;
packagedtask p1;
packagedtask p2;
p2 = std::move(p1); // does not cause the error
auto p3 = std::move(p2); // causes the error
}
Trawling through the code, packaged_task has embedded typedefs as follows;
typedef typename _P_arg_type<_Ret>::type _Ptype;
typedef _Promise<_Ptype> _MyPromiseType;
_P_arg_type offers a non-void type when the return type is void. The packaged_task move constructor contains a reference to the internal _Promise as _Promise<_Ret>;
_MyPromise(_STD forward<_Promise<_Ret> >(_Other._MyPromise))
This then becomes _Promise<void> which in turn generates further invalid code that generates the list of errors seen. It should probably be;
_MyPromise(_STD forward<_MyPromiseType >(_Other._MyPromise))
// possibly even using a move
As the move assignment operator does.
As a workaround, consider adding a "dummy" or "unusable" return type of some sort;
struct unusable {};
Or just simply an int or boost as you have already suggested.

Related

Error making tuple containing a unique_ptr

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);

How to emplace a function wrapper with some arguments from local variables into container with MSVC2015?

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));

(Default) construct an object for every variadic type

Consider this code snippet:
void Foo(std::string str1, std::string str2) {}
template<typename... Types>
void Bar()
{
Foo(Types{}...); // wont compile
}
Bar<std::string, std::string>();
What I want to do here is to default construct two std::string objects inside the Bar method and pass them to Foo. However my vain attempts (one of them being in the snippet) wont compile so I am wondering whether this is even possible.
I compiled with VC 2013, which throws compiler errors at me. As stated in the comments, other compilers can handle it. Can anyone tell whether the above snippet is standard conform?
It's a problem in the MSVC variadic template expansion process; when it unpacks the list of types it fails to recognise them as suitable for a constructor call. As a workaround, you can perform a type transformation to force the compiler to recognise them:
template<typename T> using identity_t = T; // NEW CODE
void Foo(int, int);
template<typename... Types>
void Bar()
{
Foo(identity_t<Types>{}...); // use identity type transformation
}
int main() {
Bar<int, int>();
}
I haven't managed to find an issue number yet.
This crashes the VC 2013 compiler for me. The errors seem to indicate that it has some problems parsing the code. So when the compiler crashes it must be a compiler bug.
1>main.cpp(23): error C2144: syntax error : 'std::string' should be preceded by ')'
1> main.cpp(28) : see reference to function template instantiation 'void Bar<std::string,std::string>(void)' being compiled
1>main.cpp(23): error C2660: 'Foo' : function does not take 0 arguments
1>main.cpp(23): error C2143: syntax error : missing ';' before '{'
1>main.cpp(23): error C2143: syntax error : missing ';' before ','
1>c1xx : fatal error C1063: INTERNAL COMPILER ERROR
1> Please choose the Technical Support command on the Visual C++
1> Help menu, or open the Technical Support help file for more information
1>cl : Command line warning D9028: minimal rebuild failure, reverting to normal build
1>
1>Build FAILED.

member hook implementation for splay_multiset in Boost::Intrusive

I was implementing boost::intrusive for one of my project on visual C++ 2008 and i stumbled upon a problem. i am using splay hooks for splay_multiset containers. I have defined splay hook publically under MyClass (code below).
#include <boost/intrusive/unordered_set.hpp>
#include <boost/intrusive/splay_set.hpp>
#include <iostream>
using namespace boost::intrusive;
class MyClass
{
int int_;
public:
MyClass(int i)
: int_(i)
{}
splay_set_member_hook<link_mode<normal_link> > memberSplayHook;
//**OPTION-1**
//PROBLEM CODE SEGMENT ++
//typedef member_hook<MyClass, splay_set_member_hook<link_mode<normal_link> >, &MyClass::memberSplayHook> MemberOption;
//typedef splay_multiset<MyClass, MemberOption> MemberMultiSet;
//PROBLEM CODE SEGMENT --
MemberMultiSet mmset;
};
//**OPTION-2**
//WORKING CODE SEGMENT ++
typedef member_hook<MyClass, splay_set_member_hook<link_mode<normal_link> >, &MyClass::memberSplayHook> MemberOption;
typedef splay_multiset<MyClass, MemberOption> MemberMultiSet;
//WORKING CODE SEGMENT --
int main()
{
return 0;
}
The problem is, to use splay_multiset, whatever option i choose (either option-1 or 2, mention in code), in both cases i see compilation errors.
When Option-1 is enabled (option-2 is commented), i see errors below:
1>d:\projects\sampleproject\sample.cpp(21) : error C2327: 'MyClass::memberSplayHook' : is not a type name, static, or enumerator
1>d:\projects\sampleproject\sample.cpp(21) : error C2065: 'memberSplayHook' : undeclared identifier
1>d:\projects\sampleproject\sample.cpp(22) : error C3203: 'member_hook' : unspecialized class template can't be used as a template argument for template parameter 'O1', expected a real type
While, when Option-2 is enabled (option-1 is commented out), i dont see undeclared identifier error msg as these errors coming with option-1. But i do see errors like below (which are obvious).
1>d:\projects\sampleproject\sample.cpp(25) : error C2146: syntax error : missing ';' before identifier 'mmset'
1>d:\projects\sampleproject\sample.cpp(25) : error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
My question is why i am getting error in first case? What can i do to get pass this issue?
Boost member hooks have (always?) been broken, since they don't compile with Visual C++.
I don't have a VS at hand to check for the precise error message so I might be wrong (but reading 'member hooks' and 'Visual C++' always triggers 'there's a problem'-mode), but do try to check this:
http://permalink.gmane.org/gmane.comp.lib.boost.user/56875
EDIT: Don't take the headline literally -- the same applies to Visual C++ 2010 and 2012. All my member hooks use this workaround; at some point I might even try to understand what it does, or more importantly, how to package it into a more comfortable setup for less "I need to find a previous implementation of this workaround so I can copy-and-modify it"...

Filling std::map with std::transform (error: cannot deduce argument)

I'm trying to fill std::map with std::transform. Next code compiles without error:
std::set<std::wstring> in; // "in" is filled with data
std::map<std::wstring, unsigned> out;
std::transform(in.begin(), in.end()
, boost::counting_iterator<unsigned>(0)
, std::inserter(out, out.end())
, [] (std::wstring _str, unsigned _val) { return std::make_pair(_str, _val); }
);
But If I replace string
, [] (std::wstring _str, unsigned _val) { return std::make_pair(_str, _val); }
with
, std::make_pair<std::wstring, unsigned>
or
, std::ptr_fun(std::make_pair<std::wstring, unsigned>)
I get errors:
foo.cpp(327): error C2784: '_OutTy *std::transform(_InIt1,_InIt1,_InTy (&)[_InSize],_OutTy (&)[_OutSize],_Fn2)' : could not deduce template argument for '_InTy (&)[_InSize]' from 'boost::counting_iterator<Incrementable>'
with
[
Incrementable=unsigned int
]
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\algorithm(1293) : see declaration of 'std::transform'
foo.cpp(327): error C2784: '_OutTy *std::transform(_InIt1,_InIt1,_InIt2,_OutTy (&)[_OutSize],_Fn2)' : could not deduce template argument for '_OutTy (&)[_OutSize]' from 'std::insert_iterator<_Container>'
with
[
_Container=std::map<std::wstring,unsigned int>
]
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\algorithm(1279) : see declaration of 'std::transform'
foo.cpp(327): error C2784: '_OutIt std::transform(_InIt1,_InIt1,_InTy (&)[_InSize],_OutIt,_Fn2)' : could not deduce template argument for '_InTy (&)[_InSize]' from 'boost::counting_iterator<Incrementable>'
with
[
Incrementable=unsigned int
]
C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\algorithm(1267) : see declaration of 'std::transform'
foo.cpp(327): error C2914: 'std::transform' : cannot deduce template argument as function argument is ambiguous
and so on...
Please explain what is the problem is with compilation?
UPDATE: Thanks for answers. I realized, that it is MSVC2010 bug. By the way the line
&std::make_pair<const std::wstring&, const unsigned&>
causes the same error
This is a bug in the Visual C++ library implementation. The following program demonstrates the issue:
#include <utility>
int main()
{
&std::make_pair<int, int>;
};
This program yields the error:
error C2568: 'identifier' : unable to resolve function overload
In the C++ language specification, make_pair is not an overloaded function. The Visual C++ 2010 library implementation includes four overloads taking various combinations of lvalue and rvalue references.
While an implementation of the C++ Standard Library is allowed to add overloads for member functions, it isn't allowed to add overloads for nonmember functions, thus this is a bug.
The bug was reported and will be fixed in the next version of Visual C++. However, as STL notes in the resolution to that bug, you'll need to make the template arguments to std::make_pair lvalue references:
&std::make_pair<const std::wstring&, const unsigned&>
g++ 4.4.5 compiles it without errors. Seems to be a Visual Studio 10 defect.