Problem replacing boost::bind with std::tr1::bind - c++

I have the following code which compiles and runs fine under Visual Studio 2008 SP1.
#include <functional>
#include <iostream>
#include <boost/bind.hpp>
#include <boost/function.hpp>
#include <boost/scoped_ptr.hpp>
#include <boost/utility.hpp>
class NoncopyableObject : public boost::noncopyable
{
public:
NoncopyableObject(int x) : x_(x) {}
int getValue() const {return x_;}
private:
int x_;
};
template<class F>
class MenuItemDispatcher
{
public:
MenuItemDispatcher(F f) : f_(f) { }
void operator ()(NoncopyableObject& w) const
{
// Invoke the functor
f_(w);
}
private:
typedef boost::function1<void,NoncopyableObject&> FUNC;
FUNC f_;
};
void MenuItem()
{
std::cout << "in MenuItem()\n";
}
template<class F>
MenuItemDispatcher<F> MakeMenuItemDispatcher(F f)
{
return MenuItemDispatcher<F>(f);
}
int main()
{
NoncopyableObject obj(7);
MakeMenuItemDispatcher(boost::bind(&MenuItem))(obj);
}
If I change the boost::bind to std::tr1::bind in main(), I get an error:
error C2248: 'boost::noncopyable_::noncopyable::noncopyable' : cannot access private member declared in class 'boost::noncopyable_::noncopyable'.
This diagnostic occurred in the compiler generated function 'NoncopyableObject::NoncopyableObject(const NoncopyableObject &)'
So it's trying to generate a copy constructor for NoncopyableObject. Anyone know why this might be so please? MenuItemDispatcher's call operator takes a reference to a NoncopyableObject, so I am struggling to see what's going wrong.

This appears to be a difference in how bind is implemented in MS Visual Studio (including 2010) and GNU gcc (I tested 4.4.1 and 4.5.2, both of which work the way you expected)
Consider the following code, given your definitions
auto b = boost::bind(&MenuItem);
NoncopyableObject obj(7);
b(obj); // OK in VS and GCC
replacing boost::bind with std::bind (I'm using 2010, the error message appears to be the same as in your 2008)
auto b = std::bind(&MenuItem);
NoncopyableObject obj(7);
b(obj); // compile error in VS 2010 SP1, OK in GCC
b(std::reference_wrapper<NoncopyableObject>(obj)); // OK in both
So, what happens is that MS's bind() makes a copy of its argument even if the argument is not going to be used, while boost's and GCC's bind() does not bother with that argument at all.
I was able to get your example to compile and run (on 2010) by changing the FUNC typedef to
typedef boost::function1<void, std::tr1::reference_wrapper<NoncopyableObject> > FUNC;

Related

Weird error from Visual C++: No default constructor for promise type

Suppose I want to use coroutines with C++20 and restrict the promise type to accept only functions getting one argument of type int &. I write the following code:
#include <coroutine>
struct task {
struct promise_type {
promise_type(int &) {}
task get_return_object() { return {}; }
std::suspend_never initial_suspend() { return {}; }
std::suspend_never final_suspend() noexcept { return {}; }
void return_void() {}
void unhandled_exception() {}
};
};
task my_task(int &) {
co_await std::suspend_never{};
}
int main() {
int x = 5;
my_task(x);
}
This compiles and works fine, both with GCC version 10+ and Visual Studio 2019 version 16.8+.
However, Visual Studio 2019 always complains that no default constructor exists for class "task::promise_type":
This error does not occur if I do not use a reference (e.g. int instead of int & as the argument type).
GCC does not show any warning or error, with and without the reference.
Am I doing something wrong?
Is this prohibited by the standard?
Or is it just a weird quirk of IntelliSense?
This seems to be a problem of IntelliSense and should work fine. To resolve the intellisense error, a constructor can be added just for IntelliSense:
#ifdef __INTELLISENSE__
promise_type();
#endif

Error C2079 'std::pair<Dummy<int>,Dummy<int>>::first' uses undefined class 'Dummy<int>'

The following code snippet compiles just fine with GCC 9.1 and Clang 6.0 under C++11/14/17 standards, but refuses to compile with Visual Studio 2019. I can change the return of getDummies() to auto and VS will compile with C++14/17 standards, but this breaks C++11 compatibility on all compilers, which I need to keep.
#include <cstdlib>
#include <utility>
template<typename T>
class Dummy
{
public:
//static auto getDummies() // Works but breaks C++11 compatibility
static std::pair<Dummy<int>, Dummy<int>> getDummies()
{
return std::make_pair(Dummy<int>{}, Dummy<int>{});
}
};
int main()
{
auto dummies = Dummy<int>::getDummies(); // Error C2079
return EXIT_SUCCESS;
}
The class Dummy is not fully defined at the point that the getDummies() function is defined, inside the class.
You can declare the function in the class then define it outside the class, like:
template<typename T>
class Dummy
{
public:
static std::pair<Dummy<int>, Dummy<int>> getDummies();
};
template<typename T>
std::pair<Dummy<int>, Dummy<int>> Dummy<T>::getDummies()
{
return std::make_pair(Dummy<int>{}, Dummy<int>{});
}

Lambdas, Is this keyword needed to disambiguate const/non-const member functions?

When I use MSVC to compile this program, I receive the error,
"Example::bar ambiguous call to overloaded function"
Then, I found that the this keyword was able to resolve the error. Surprised, I used rextester and found that both Clang and GCC were able to compile the program without the this keyword.
Here is the program in question.
#include <iostream>
class Example {
public:
Example() {
auto lambda = [this]() {
//this->bar<int>(); // Using this allows the program to compile and run successfully.
bar<int>(); // This doesn't work in MSVC
};
lambda();
}
template<typename T>
void bar() {
std::cout << "(non-const) bar\n";
}
template<typename t>
void bar() const {
std::cout << "(const) bar\n";
}
};
int main() {
Example example;
}
Ultimately I am asking, is this keyword needed in a lambda to disambiguate between const and non-const member functions and whether MSVC is correct or GCC and Clang are correct.
I am using Visual Studio 2017 and the full version of MSVC is 191627027

C++ - Errors when trying to insert class into map

I have a map like so map<string, unique_ptr<Base>> variables and I am trying to insert data into the map variables.insert(make_pair("foo", new Int(10))) but I am getting to following errors:
error: no matching function for call to ‘std::map<std::__cxx11::basic_string<char>, std::unique_ptr<Base>>::insert(std::pair<const char*, Int*>)’
variables.insert(make_pair("test", new Int(10)));
error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
template<typename _Pair, typename = typename
This is my code:
class Base {
public:
Base() {};
virtual ~Base() {};
};
class Int : public Base {
public:
Int(int i) {
this->i = i;
}
Int operator=(int i) {
this->i = i;
}
int i;
};
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", new Int(10)));
}
I think I need a fresh pair of eyes to look at this I'm not sure what this issue is, thanks!
Edit
I'm trying to make a heterogeneous map and there's a class for each data type. But I still get the same error no matter how many there are.
Note: This answer only applies to older versions of the main three compilers:
GCC: Applies to 5.3.1 or earlier. May apply to any version earlier than 6.1.0, but I haven't tested this.
Clang: Applies to 3.7.1 or earlier. May apply to any version earlier than 3.8.0, but I haven't tested this.
Visual Studio: Applies to 19.00.23506.0 or earlier. May apply to any version earlier than 19.00.23720.0, but I haven't tested this.
Conversely, if you have GCC 6.1.0 or later, Clang 3.8.0 or later, or Visual Studio 19.00.23720.0 or later, the original code should compile as is, without either of the modifications suggested in this answer.
[Thanks goes to AndyG for pointing out that it works with later versions of GCC & Clang.]
The problem appears to be that it isn't creating your unique_ptr from your raw pointer.
If you can use C++14, try std::make_unique().
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", make_unique<Int>(10)));
}
If you can't, then try something like this:
void set() {
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", unique_ptr<Int>(new Int(10))));
}
Interestingly, I noticed a slight difference in how different compilers handle this. Using the following slightly modified version of your code as a test program:
#include <map>
#include <memory>
#include <iostream>
class Base {
public:
Base() {};
virtual ~Base() {};
};
class Int : public Base {
public:
Int(int i) {
this->i = i;
}
Int& operator=(int i) {
this->i = i;
// You forgot to return something.
return *this;
}
int i;
};
void set() {
using namespace std;
map<string, unique_ptr<Base>> variables;
variables.insert(make_pair("test", new Int(10)));
// C++14:
// variables.insert(make_pair("test", make_unique<Int>(10)));
// C++11:
// variables.insert(make_pair("test", unique_ptr<Int>(new Int(10))));
// Cheap hack for testing.
cout << static_cast<Int*>(variables["test"].get())->i << endl;
}
int main() {
set();
}
Most compilers* will fail to compile this, unless the initial line is commented out and either of the fixes is uncommented. However, the online MSVC compiler seemed to be able to compile it fine, without needing to uncomment either of the lines. Curiously, the version of MSVC available on Rextester failed to compile it without uncommenting one of the two lines.
* Tested online, with TutorialsPoint GCC, MSVC 2015 online, and Rextester Clang, GCC, and MSVC.

VS 2015 Error when using nested lambda

Here is a toned down version of my use case which compiles fine on gcc 4.9.3 and clang 3.7 but fails on VS 2015 Update 2.
#include <functional>
#include <string>
#include<memory>
namespace A {
using handle = std::function<void(std::string)>;
void func(std::string, handle) {
}
}
class B : public std::enable_shared_from_this<B> {
public:
void func();
};
void B::func()
{
auto && cast = std::static_pointer_cast<B>(shared_from_this());
auto const another_variable = [cast]() -> void
{
A::func("hello", [&cast](std::string){ } );
};
}
int main() {
return 0;
}
Here are the errors that I get
Error(s):
source_file.cpp(23): error C2440: '<function-style-cast>': cannot convert from 'const std::shared_ptr<_Ty>' to 'B::func::<lambda_4a58826445f3685613b078cf10fc9f7e>::()::<lambda_8290a9c207487c2dc2e26a5b929b4850>'
with
[
_Ty=B
]
source_file.cpp(23): note: No constructor could take the source type, or constructor overload resolution was ambiguous
source_file.cpp(23): error C2660: 'A::func': function does not take 1 arguments
Interestingly, it compiles fine on VS 2013 as well. Am I missing something very obvious?