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.
Related
Recently, I've started using MSVC to compile a code which was always compiled with GCC and Clang. Some piece of this code produces an interesting compilation error (truncated):
C:/data/msvc/14.33.31424-Pre/include\future(311) error C2678: binary '=': no operator found which takes a left-hand operand of type 'const Result' (or there is no acceptable conversion)
<source>(7): note: could be 'Result &Result::operator =(Result &&)'
<source>(7): note: or 'Result &Result::operator =(const Result &)'
Minimal example of this piece of code:
#include <future>
#include <iostream>
struct Result {
int data{0};
};
// getting rid of constness resolves the problem for MSVC
using result_t = const Result;
using promise_result_t = std::promise<result_t>;
auto compute_result(promise_result_t result)
{
Result some_result{10};
result.set_value(std::move(some_result));
}
int main()
{
promise_result_t my_promise;
auto my_future = my_promise.get_future();
std::thread thread(compute_result, std::move(my_promise));
std::cout << "result: " << my_future.get().data;
thread.join();
return 0;
}
Successful compilation with Clang 11: https://godbolt.org/z/o6Ge85rxG
Successful compilation with GCC 12: https://godbolt.org/z/x1rhqhfGT
Error with MSVC 19: https://godbolt.org/z/4jMYhTj3n
It is quite clear that removal of const for std::promise storage solves the problem, but I'm curious if anyone has tried to dive deep into the implementations of std::promise for different compilers.
What might be the difference that allows this code to compile and work using GCC and Clang, yet produce a compilation error when using MSVC? (Operating via pointers on stored data in GCC and Clang?)
Looks like an MSVC issue, reported here:
https://developercommunity.visualstudio.com/t/std::promise-works-incorrectly-for-const/10092031
and linked to the issue on GitHub:
https://github.com/microsoft/STL/issues/2599
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.
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
I'm trying to update a old project that has been building with visual studio 2005 to uses visual studio 2012, and I'm getting an error that I cant solve.
The code that works fine under VS2005:
#include <iostream>
#include <string>
#include <sstream>
using std::cout;
using std::wcout;
using std::endl;
using std::wstring;
using std::string;
class Value
{
public:
Value(const wstring& value)
{
v = value;
}
Value(Value& other)
{
this->v = other.v;
}
template<typename T>
operator T() const
{
T reply;
std::wistringstream is;
is.str(v);
is >> reply;
return reply;
}
operator wstring() const
{
return v;
}
private:
wstring v;
};
int main()
{
Value v(L"Hello World");
wstring str = v;
wcout << str << endl;
Value int_val(L"1");
int i = int_val;
cout << i + 1 << endl;
return 0;
}
When I'm compiling this under VS2012 I get an error on the line "wstring str = v;", the error is:
error C2440: 'initializing' : cannot convert from 'Value' to 'std::basic_string<_Elem,_Traits,_Alloc>'
1> with
1> [
1> _Elem=wchar_t,
1> _Traits=std::char_traits<wchar_t>,
1> _Alloc=std::allocator<wchar_t>
1> ]
1> No constructor could take the source type, or constructor overload resolution was ambiguous
I can kinda fix it by changing the operator signature from 'operator wstring() const' to 'operator const wstring&() const'. But why does the original code not work, even though it works in VS2005.
I'm not getting an error on the line "int i = int_val;".
This also compiles and runs fine with GCC (g++) in cygwin (version 4.5.3).
Update
To really simulate my real problem there was some information left out in the sample code above. In between the Value class and the usage is a few other classes. One that look like this:
class Config
{
public:
virtual Value getValue(const string& key) const = 0;
Value operator()(const string& key)
{
return getValue(key);
}
};
And the usage
const wstring value2 = config("key");
That will give the error above when compiling but also IntelliSense will give other hints on whats wrong and it says: "More than one user-defined conversion from "Value" to "const std::wstring" applies:" and it points at both the regular constructor and the move constructor of basic_string. So it seem to have something to do with rvalues to do and I have been reading up on that, and understand the basics. But there is probably a lot I am missing.
I find that I can fix this problem by changing the usage to:
const wstring&& value = config("key");
Then it seem like the VS2012 compiler understand which constructor it should use then.
Questions:
* Are there a way to not use && in this example?
* What is really happening here?
I put up the sample code on GitHub:
https://github.com/Discordia/ImplicitTypeConversion
In simple (hopefully not simplified) terms, with C++11, you'll have to start thinking of references in terms of lvalue and rvalue. Basically, C++11 gives you the ability to handle operations on references differently depending on whether or not you are dealing with a "temporary" object. This gives you ability to do things like move data internal to your object rather than copy in different situations. The down side to this is the effect you are seeing, where old code is not specific enough about which you are dealing with. There's more to it than that, it's not really something that can be fully explained in a short SO answer, but previous answers gave some good places to start. I would rework your code to provide both rvalue and lvalue operators (which it sounds like you're already on your way to doing).
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?