C++ Compiler Error C2280 "Attempting to Reference a Deleted Function" in Visual Studio 2013 and 2015

C++ Compiler Error C2280 attempting to reference a deleted function in Visual Studio 2013 and 2015

From [class.copy]/7, emphasis mine:

If the class definition does not explicitly declare a copy constructor, a non-explicit one is declared implicitly.
If the class definition declares a move constructor or move assignment operator, the implicitly declared copy
constructor is defined as deleted
; otherwise, it is defined as defaulted (8.4). The latter case is deprecated if
the class has a user-declared copy assignment operator or a user-declared destructor.

There is an equivalent section with similar wording for copy assignment in paragraph 18. So your class is really:

class A
{
public:
// explicit
A(){}
A(A &&){}

// implicit
A(const A&) = delete;
A& operator=(const A&) = delete;
};

which is why you can't copy-construct it. If you provide a move constructor/assignment, and you still want the class to be copyable, you will have to explicitly provide those special member functions:

    A(const A&) = default;
A& operator=(const A&) = default;

You will also need to declare a move assignment operator. If you really have a need for these special functions, you will also probably need the destructor. See Rule of Five.

Nested union compilation error: C2280 attempting to reference a deleted function

1. non-trivial union members

One of the problems in your code is the union.

unions only implicitly define their special member functions if their members have trivial implimentations for them.

-> Once you add a member to a union that implements a special member function you'll have to manually implement that one for your union.

From the c++ standard:

At most one non-static data member of a union may have a brace-or-equal-initializer. [Note: if any non-static data member of a union has a non-trivial default constructor (12.1), copy constructor (12.8), move constructor (12.8), copy assignment operator (12.8), move assignment operator (12.8), or destructor (12.4), the corresponding member function of the union must be user-provided or it will be implicitly deleted (8.4.3) for the union. — end note ]

Example:

// only trivial members: the compiler will provide all functions for you
union A {
int i;
float f;
double d;

// member functions provided by your compiler
A() = default;
A(const A&) = default;
A(A&&) = default;
A& operator=(const A&) = default;
A& operator=(A&&) = default;
~A() = default;
};

// std::string & std::vector have non-trivial constructors, assignment operators and destructors
// so the member functions will be deleted.
union B {
int i;
std::string s;
std::vector<int> v;

// member functions provided by your compiler
B() = delete;
B(const B&) = delete;
B(B&&) = delete;
B& operator=(const B&) = delete;
B& operator=(B&&) = delete;
~B() = delete;
};

godbolt example with your code

The reasoning behind this is that there is no way the compiler could actually generate those functions. For example the constructor of union B would need to know if it needs to call the constructor of std::string, std::vector or none at all - but that depends on which member you initialize which the compiler doesn't know yet.

Same thing for the destructor of union B - which destructor should it call? std::string::~string() ? or std::vector<int>::~vector()? or none at all in the int case? The union doesn't know which member is the active one so there's no way to provide a sensible destructor.

So the compiler leaves the responsibility of actually implementing all those special functions up to you.

A very simple example of implementing a two-type generic union could look like this:


template<class T, class U>
struct variant {
private:
enum {
IS_NONE,
IS_T,
IS_U
} activeMember;

union {
T t;
U u;
char dummy;
};

public:
variant() : activeMember(IS_NONE), dummy() {}
variant(T const& _t): activeMember(IS_T), t(_t) {}
variant(U const& _u): activeMember(IS_U), u(_u) {}
variant(variant const& other): variant() { *this = other; }

variant& operator=(variant const& other) {
if(&other != this) {
reset();
activeMember = other.activeMember;
if(other.activeMember == IS_T)
new (&t) T(other.t);
else if(other.activeMember == IS_U)
new (&u) U(other.u);
}
return *this;
}

variant& operator=(T const& _t) {
reset();
activeMember = IS_T;
new (&t) T(_t);
return *this;
}

variant& operator=(U const& _u) {
reset();
activeMember = IS_U;
new (&u) U(_u);
return *this;
}

explicit operator T const&() {
if(activeMember != IS_T) throw std::domain_error("variant is not T!");
return t;
}

explicit operator U const&() {
if(activeMember != IS_U) throw std::domain_error("variant is not U!");
return u;
}

explicit operator bool() {
return activeMember != IS_NONE;
}

~variant() { reset(); }

void reset() {
if(activeMember == IS_T)
t.~T();
else if(activeMember == IS_U)
u.~U();
activeMember = IS_NONE;
}
};

godbolt example

Which could be used like this:

variant<int, std::string> v = 12;
v = "MIAU";

Notice that we need to initialize one of the union members in the constructors, as well as call their respective destructors as needed.

If we want to switch the active member after construction we also need to destruct the previosly active union member first, then use placement-new to construct the new value.

1.1 using std::variant

If you can use C++17 i'd recommend using std::variant instead of the union, since that basically does the exact same thing as the variant class i posted above and more.



2. memcpy of non-trival types

You use memcpy( &m_Data._Ttype, &_Ttype, sizeof(T) ); both in the constructor and assignment operator of your class.

You are only allowed to copy objects with memcpy if they are trivially copyable, i.e.:

static_assert(std::is_trivially_copyable<T>::value, "T is not trivially copyable!");

Given the compile error you got your T is most likely not trivially copyable, so using memcpy in this case leads to undefined behaviour.

You can instead use placement new to call the copy- or move constructor of T, e.g.:

template<class T>
Clustering<T>& Clustering<T>::operator=(T const& t)
{
new (&m_Data._Ttype) T(t);
return *this;
};

Also don't forget to call the destructor for your T (if it's not trivially destructable) in your ~Clustering() destructor (otherwise you leak your T!):

template<class T>
Clustering<T>::~Clustering() {
if(/* union actually contains T */)
m_Data._Ttype.~T();
}



  1. Full working example

In your example you could write Clustering like this:

template <typename T> 
class Clustering
{
friend CPlayer;
public:
union
{
T _Ttype;
CPlayer* m_player;
};
bool containsT;
public:
Clustering() : containsT(false), m_player(nullptr) {};
Clustering(T const& t) : containsT(true), _Ttype(t) {};

Clustering& operator=(T const& t)
{
// cleanup old T if needed
if(containsT)
_Ttype.~T();

containsT = true;
new (&_Ttype) T(t);

return *this;
};

~Clustering() {
if(containsT)
_Ttype.~T();
};
};

working godbolt example

(notice that we can avoid cleaning up m_player, since pointers are trivial.)

C++ ERROR: C2280- compiler error that references deleted function?

As Token doesn't have a default constructor (a constructor which can be called without any parameters), and token_stream contains Token, the compiler cannot generate default constructor for token_stream.

Two possible solutions:

  1. Add a default constructor to Token
  2. Add a default constructor to token_stream, which initializes buffer to some value

Attempting to reference Deleted function shared_ptr

Apparently "poorly defined member variables" can cause default functions to be deleted. (kind of strange)

https://stackoverflow.com/a/37517125/2934222

Try altering how you've defined this method maybe:

virtual Json to_json() const = 0;

My Code is attemping to a deleted function?

The ifstream type has no copy constructor because it was intentionally deleted, meaning that you cannot pass it by value as you are doing in the readProductInformation function. More information about ifstream's constructors can be found here, most importantly the following

(3) copy constructor (deleted)
Deleted (no copy constructor).

In order to fix this, just pass the ifstream object by reference instead of by value. This means that the object accessed in the function is actually the same object that is passed in. Changes made to this object are not restricted to inside the function. Here is a good post that goes into more detail about the difference.

So you simply have to change it to

bool readProductInformation(ifstream& f, ProductList& productList)

Why would someone intentionally delete a copy constructor? Because sometimes it doesn't make sense for specific objects to be copied, and if you don't specifically delete an object's copy constructor, the compiler is smart enough to sometimes make one for you allowing you to do what was unintended (copy). Here is a somewhat dense but good source explaining deleting and defaulting functions.

Getting C2280 (attempting to reference a deleted function) when using future

The error tells you that response objects can't be copied and that you are trying to do just that.

struct response { 
std::istream& is; // can't be copied: istream( const istream&) = delete;
Poco::Net::HTTPResponse& response; // also not copyable or movable
};

There is however nothing in the code you've shown that tries to do this.

receiveResponse() returns a reference to a std::istream which becomes problematic in case it throws. When you catch an exception you don't have anything to return, so you don't - and enter the land of Undefined Behaviour.

You might as well read the data inside the async lambda and store that in your RES directly.

#include <Poco/Exception.h>
#include <Poco/Net/HTTPRequest.h>
#include <Poco/Net/HTTPResponse.h>
#include <Poco/Net/HTTPSClientSession.h>
#include <Poco/Net/SecureStreamSocket.h>
#include <Poco/URI.h>

#include <future>
#include <iostream>
#include <map>
#include <vector>
#include <memory>

// a slightly modified version of your RES struct
struct RES {
std::vector<std::string> data{}; // the document data

// using a unique_ptr to make HTTPResponse easier to move
std::unique_ptr<Poco::Net::HTTPResponse>
response = std::make_unique<Poco::Net::HTTPResponse>();

bool ok = false; // if reading was done without an exception
};

class HttpClient {
public:
static std::future<RES> get(Poco::Net::HTTPSClientSession& session,
Poco::URI url,
std::map<std::string, std::string> headers = {});
};

std::future<RES> HttpClient::get(Poco::Net::HTTPSClientSession& session,
Poco::URI url,
std::map<std::string, std::string> headers) {
return std::async(std::launch::async, [&session, url, headers]() {

RES res;

try {
Poco::Net::HTTPRequest request(Poco::Net::HTTPRequest::HTTP_GET,
url.getPathAndQuery(),
Poco::Net::HTTPMessage::HTTP_1_1);

// add request headers
for(const auto&[field, value]: headers)
request.add(field, value);

session.sendRequest(request);
std::istream& is = session.receiveResponse(*res.response);

// read document data
std::string line;
while(std::getline(is, line))
res.data.push_back(line);

res.ok = true; // reading was done without an exception
} catch(Poco::Exception& exc) {
std::cout << exc.displayText().c_str() << "\n";
}

// always return according to what you declared
return res;
});
}

Example usage:

class SSLInitializer {
public:
SSLInitializer() { Poco::Net::initializeSSL(); }
~SSLInitializer() { Poco::Net::uninitializeSSL(); }
};

int main() {
SSLInitializer sslInitializer;

Poco::URI uri{"https://www.google.com/"};

const Poco::Net::Context::Ptr context = new Poco::Net::Context(
Poco::Net::Context::CLIENT_USE, "", "", "", Poco::Net::Context::VERIFY_NONE, 9,
false, "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH");

Poco::Net::HTTPSClientSession sess(uri.getHost(), uri.getPort(), context);

std::future<RES> fut_res = HttpClient::get(sess, uri);

fut_res.wait();

RES res = fut_res.get();
std::cout << std::boolalpha << "Response OK: " << res.ok << "\n---\n";
if(res.ok) {
Poco::Net::HTTPResponse& header = *res.response

std::cout << "HTTPResponse header:\n";
for(const auto& [field, value] : header) {
std::cout << field << " = " << value << "\n";
}

std::cout << "--- DOCUMENT DATA ---\n";
for(const auto& s : res.data) {
std::cout << s << "\n";
}
}
}

QT : attempting to reference a deleted function

I do not observe the error you indicate, I also prefer to use QVariantList instead of QList <T* > to export a list of QObjects:

main.cpp

using namespace ADACEL::SPEECH::SRA;

QVariantList statusRows;
statusRows.append(QVariant::fromValue(new StatusRow("TITLE_AUDIO_PROVIDER", "ICON_OK")));
statusRows.append(QVariant::fromValue(new StatusRow("TITLE_ASR_ENGINE", "ICON_NONE")));
statusRows.append(QVariant::fromValue(new StatusRow("TITLE_POST_PROCESSOR", "ICON_NONE")));
statusRows.append(QVariant::fromValue(new StatusRow("TITLE_ADAPTER", "ICON_ERROR")));

QQuickView view;
view.rootContext()->setContextProperty("statusInfo", QVariant::fromValue(statusRows));


Related Topics



Leave a reply



Submit