Use of custom subscript operator with Boost.Lambda - c++

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?

Related

Using lambda expression as Compare for std::set, when it's inside a vector

I want to use a lambda expression as custom Compare for a std::set of integers. There are many answers on this site explaining how to do this, for example https://stackoverflow.com/a/46128321/10774939. And indeed,
#include <vector>
#include <set>
#include <iostream>
int main() {
auto different_cmp = [](int i, int j) -> bool {
return j < i;
};
std::set<int, decltype(different_cmp)> integers(different_cmp);
integers.insert(3);
integers.insert(4);
integers.insert(1);
for (int integer : integers) {
std::cout << integer << " ";
}
return 0;
}
compiles and outputs
4 3 1
as expected. However, when I try to put this set in a vector with
std::vector<std::set<int, decltype(different_cmp)>> vec_of_integers;
vec_of_integers.push_back(integers);
the compiler complains. I'm using Visual Studio 2017 and I get different compiler errors depending on the surrounding code. In the above example, it's
1>c:\program files (x86)\microsoft visual studio\2017\community\vc\tools\msvc\14.16.27023\include\utility(77): error C2664: 'void std::swap(std::exception_ptr &,std::exception_ptr &) noexcept': cannot convert argument 1 from '_Ty' to 'std::exception_ptr &'
1> with
1> [
1> _Ty=main::<lambda_48847b4f831139ed92f5310c6e06eea1>
1> ]
Most of the errors I've seen so far with this seem to have to do with copying the set.
So my question is:
Why does the above code not work and how can I make it work, while still using a locally defined lambda?
This seems to be a bug in MS compiler as it compiles well with GCC and Clang.
To make it work in MS Compiler (Visual Studio 2017) you can do this:
std::vector<std::set<int, decltype(different_cmp)>> vec_of_integers{integers};
This compiles cleanly. See here.

Template deduction error

Note: pls don't be confused with other Stackoverflow questions that have the same title/errocode -- they are mostly due to missing #include <string> but it's not the issue here.
I'm reading Pretty-print C++ STL containers question and downloaed Kerrek's code from his GitHub Project cxx-prettyprint, when I try compile it (my environment is Windows 7, Visual Studio 2013, compiled project as a Console Application "Use Multi-Byte Character Set"), hit a template deduction error.
It's a bit weird as suggested by Mike Kinghan in the comment, it does compile compiles and runs fine with the current MSVC++ : see it online.
I'm confused, there must be something wrong with my configuration. I created a blank new Windows Console Application, and added Kerrek's code in, focus on a vector of string test cast, removed other scenarios such as set/map etc:
int main(int argc, char* argv[])
{
std::vector<std::string> v;
v.push_back("hello, world");
v.push_back("2nd line");
v.push_back("last line");
std::cout << v;
}
, now hit a error:
Error 1 error C2679: binary '<<' : no operator found which takes a
right-hand operand of type
'std::vector>' (or there is no
acceptable conversion)
If I explicitly call the pretty_print::operator <<,
pretty_print::operator<<(std::cout, v);
, hit another template deduction error:
Error 1 error C2784: 'std::basic_ostream<_Elem,_Traits>
&pretty_print::operator <<(std::basic_ostream<_Elem,_Traits> &,const
pretty_print::print_container_helper
&)' : could not deduce template argument for 'const
pretty_print::print_container_helper
&' from 'std::vector>'
It only compiles if the print_container_helper is explictily created:
pretty_print::print_container_helper<std::vector<std::string>, char, ::std::char_traits<char>, pretty_print::delimiters<std::vector<std::string>, char>>
vh(v);
pretty_print::operator<<(std::cout, vh);
The full code is here: http://rextester.com/RJX76690

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

Why do I get a compilation error when using the emplace method for unordered_map?

#include <string>
#include <unordered_map>
using namespace std;
....
....
unordered_map<char, int> hashtable;
string str = "hello";
char lower = tolower(str[0]);
hashtable.emplace(lower, 1);
....
returns the following compilation errors:
1 error C2780: 'std::pair<_Ty1,_Ty2> std::_Hash<_Traits>::emplace(_Valty &&)' : expects 1 arguments - 2 provided
2 IntelliSense: no instance of function template "std::tr1::unordered_map<_Kty, _Ty, _Hasher, _Keyeq, _Alloc>::emplace [with _Kty=char, _Ty=int, _Hasher=std::hash<char>, _Keyeq=std::equal_to<char>, _Alloc=std::allocator<std::pair<const char, int>>]" matches the argument list
You are using an old version of Visual C++ which did not correctly support emplace. Probably Visual C++ 2010.
As the Visual C++ Team Blog once said:
As required by C++11, we've implemented
emplace()/emplace_front()/emplace_back()/emplace_hint()/emplace_after()
in all containers for "arbitrary" numbers of arguments (see below).
(...)
VC10 supported emplacement from 1 argument, which was not
especially useful.
The best solution would be to upgrade to the latest version of the compiler.
Following some extensions which could fix your issue
#include <utility> // for std::pair
std::unordered_map<char, int> hashtable;
char lower = 'A';
hashtable.emplace(std::pair<char, int>(lower, 1));
If your pasted code compiles seems to be depending on the underlying compiler. Handling to emplace a std::pair works for e.g. c++11--according to the spec (e.g. cplusplus.com) your code snippet should work with c++14.

Comparison operators for directory_entry are missing

Consider the following program:
#include <iostream>
#include "boost/filesystem.hpp"
int main()
{
boost::filesystem::directory_entry d("test.txt");
boost::filesystem::directory_entry e("test.txt");
if (d == e) { // <---- error C2784
std::cout << "equal" << std::endl;
}
return 0;
}
This fails to compile (Visual Studio 2005, Windows XP SP3) with 17 variations of this error:
error C2784: 'bool std::operator ==(const std::stack<_Ty,_Container> &,
const std::stack<_Ty,_Container> &)' :
could not deduce template argument for
'const std::stack<_Ty,_Container> &' from
'boost::filesystem::directory_entry'
According to the documentation (I am still using Boost 1.45), there are comparison operators defined for directory_entry, but neither me nor the compiler can find them (I checked the headers manually). Am I overlooking something? Could it be that I made a mistake when building boost, maybe by setting some option that disables these operators? Is the documentation wrong? Can anyone explain?
If you were unable to locate the operator in the header file, then maybe you have a different version of the library? In Boost 1.45, the operator is located in operations.hpp.
Ok, apparently this is only supported in the new Version of the library. Defining BOOST_FILESYSTEM_VERSION as 3 at the start of the program fixed the problem.