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
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>{});
}
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
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.
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?