The following code fragment gives the compilation error
call of overloaded ‘QString(int)’ is ambiguous with qt 4.7.3
(system is linux 64bit, debian unstable)
struct QSAConnection
{
QSAConnection() : sender(0), signal(0), function_ref() { }
QSAConnection(QObject *send, const char *sig, QSObject ref)
: sender(send), signal(QLatin1String(sig)), function_ref(ref) { }
QObject *sender;
QString signal;
QSObject function_ref;
};
Any tips?
The relevant bit is this line:
QSAConnection() : sender(0), signal(0), function_ref() { }
Since signal is a QString, the signal(0) bit is trying to call a constructor on the QString class that takes an integer as its only parameter. QString has no such constructor according to the Qt documentation. It does however have a constructor taking a char, and a QChar which has an implicit conversion from int. I expect it's ambiguous between those two.
Did you mean this instead?
QSAConnection() : sender(0), signal(), function_ref() { }
Which will default initialize signal. Note that technically it's not necessary to include it in the initializer list at all in that case.
It's a good thing. If it was not ambiguous, you might hit a null-pointer exception on QString::QString(char const* src). This is a common mistake with std::string.
Related
From what I have looked up, my syntax is correct but my compiler (VS2015) is complaining. Note, I'm using namespace ee with the class Network. Here's the code
//code that doens't work
thread clientThread(&ee::Network::clientRun, new ee::Network);
*note: in the real code I'm not calling new as an argument, I did it here to shorten code.
I've tested the functions and they work, I just can't get them to work using thread. Here is their signatures.
void serverRun();
void clientRun();
void clientRun(string ip);
My errors are:
Error C2661 'std::thread::thread': no overloaded function takes 2 arguments
abc no instance of constructor "std::thread::thread" matches the argument list
Does anyone have any insight as to what might be happening in this situation?
Ben's suggestion fixed my problem, but I'm not sure why.
The problem is with the first argument &ee::Network::clientRun. clientRun has 2 overloads, but at the point of template deduction (to deduce the types of the arguments to std::thread::thread<>) the compiler is not yet in a position to distinguish which of the overloads is more valid.
Ben's solution worked because the cast prior to the call has done the compilers' work for it - by specifying the type of Network::clientRun to be void (ee::Network*)(void) rather than the equally valid void (ee::Network*)(string).
Some examples:
#include <thread>
#include <string>
struct Network
{
void clientRun();
void clientRun(std::string);
};
int main()
{
// not ok...
// std::thread clientThread(&Network::clientRun, new Network);
// ok - tells the compiler which overload
auto member_function = static_cast<void (Network::*)()>(&Network::clientRun);
std::thread clientThreadA(member_function, new Network);
// also ok
using call_type = void (Network::*)();
std::thread clientThreadB(call_type(&Network::clientRun), new Network);
}
This is NOT C++11
I'm interested in the 3rd parameter of Microsoft's
CMapStringToOb::GetNextAssoc, which has following definition:
void GetNextAssoc(
POSITION& rNextPosition,
CString& rKey,
CObject*& rValue
) const;
Then I've got following easy code for testing: two good cases and one case with compiler error.
class CMyObject : public CObject //in order to use CMapStringToOb
{
public:
CMyObject(CString name_)
:name(name_)
{
}
void SayHello()
{
TRACE(_T("hello") + name);
}
CString name;
};
void main()
{
CMapStringToOb myMap;
myMap.SetAt(_T("a"), new CMyObject(_T("aaa")));
myMap.SetAt(_T("b"), new CMyObject(_T("bbb")));
myMap.SetAt(_T("c"), new CMyObject(_T("ccc")));
//good case 1
POSITION pos = myMap.GetStartPosition();
while (pos)
{
CString s;
CMyObject* pMine = NULL;
myMap.GetNextAssoc(pos, s, (CObject*&)pMine);
if(pMine)
{
pMine->SayHello();
}
}
//good case 2
pos = myMap.GetStartPosition();
while (pos)
{
CString s;
CObject* pObject = NULL;
myMap.GetNextAssoc(pos, s, pObject);
if(pObject)
{
CMyObject* pMine = static_cast<CMyObject*>(pObject);
pMine->SayHello();
}
}
//bad case:
//can not compile
// error C2440: 'static_cast' : cannot convert from 'CMyObject *' to 'CObject *&'
// static_cast and safe_cast to reference can only be used for valid initializations or for lvalue casts between related classes
pos = myMap.GetStartPosition();
while (pos)
{
CString s;
CMyObject* pMine = NULL;
myMap.GetNextAssoc(pos, s, static_cast<CObject*&>(pMine)); //compile error
if(pMine)
{
pMine->SayHello();
}
}
}
All I was trying to do is find an proper way to replace the C style casting to C++ style cast in this case.
Reading from this, it mentioned:
C casts are casts using (type)object or type(object). A C-style cast
is defined as the first of the following which succeeds:
const_cast
static_cast (though ignoring access restrictions)
static_cast (see above), then const_cast
reinterpret_cast
reinterpret_cast, then const_cast
Q1: Was the above list missing anything (e.g. for rValue)?
Q2: What's the proper way of translate C style cast to C++ style cast in this case ? (good case 2 works, but, is there a more concise one?)
Q3: How is the C Style cast doing for rValue? (in other words, please explain why good case 1 works)
You can't static_cast between references (or pointers) to "unrelated types." While you could static_cast from a CMyObject* to a CObject*, that isn't what you're doing here. Here you're trying to cast a reference to a pointer into a reference to another pointer. And the two pointer types do not have an inheritance relationship.
I like your "good case 2" code--I'd run with that.
For more details on the non-relatedness of your pointer types, see here: static_cast and reference to pointers
Inspired by John Zwinck, I will look from a different angle:
static_cast<CObject*>(pMine)
will succeed because type "CMyObject" generalize from type "CObject"; actually, this is done implicitly;
static_cast<CMyObject*>(pObject)
will succeed because type "CMyObject" generalize from type "CObject";
static_cast<CObject**>(&pMine)
will FAIL because type "CMyObject*" does NOT generalize from type "CObject*";
reinterpret_cast<CObject**>(&pMine)
will succeed at compile time because of "reinterpret_cast"; how about run time?
Let's make an assumption of the possible new implementation:
void CMapStringToOb::GetNextAssoc(
POSITION& rNextPosition,
CString& rKey,
CObject** ppValue)
{
*ppValue = (the pointer at the current position, point to an instance of "CMyObject");
}
So with calling this function by:
GetNextAssoc(pos, s, reinterpret_cast<CObject**>(&pMine))
the result is that "pMine" is pointing to an instance of "CMyObject";
So runtime is SAFE.
However, if we insert the key-value by (Note: CYourObject has no generalize relationship to CMyObject)
myMap.SetAt(_T("a"), new CYourObject(_T("aaa")));
and get it out by
GetNextAssoc(pos, s, reinterpret_cast<CObject**>(&pMine));
Compile time will still succeed, however, pMine is now pointing to "CYourObject", which will be UNDEFINED BEHAVIOR at runtime. (static_cast has the same issue, though)
The proper way to write that code would be to use std::map<>. Even if you insist on keeping the existing code mostly, consider fixing the interface of GetNextAssoc() to just return the pointer. In order to do that, you could simply add an overload of that function:
CObject* GetNextAssoc(
POSITION& rNextPosition,
CString& rKey,
) const {
CObject* res = 0;
GetNextAssoc(rNextPosition, rKey, res);
return res;
}
Even more, you could template that function and do the conversion to the target type there. Also, you could then use dynamic_cast, which should be used because formally, the container stores CObjects and they could have various, different types.
Now, why did I partially ignore your question? The reason is that the MFC don't follow modern coding style and in some cases, they simply do things that are frowned on. There are a bunch of justifications for that behaviour, but foremost it is age (didn't know better, didn't have proper template support) combined with compatibility concerns (can't change that now). That's not a reason to repeat these mistakes though.
In Qt 4 it is possible to automatically cast a QString to a "const char *", e.g. I could pass a QString to a function that expected a "const char *".
void myFunction(const char *parameter);
QString myString;
myFunction(myString); //works in QT4
In Qt 5 I would however get an "error C2440: 'type cast' : cannot convert from 'QString' to 'const char *'" (that is the Visual C++ 2008 compiler, other compilers would throw something similar). If I understand the documentation correctly, it is because the Qt 3 compatibility layer is not included anymore in QT5.
Of course, I could change the function call from
myFunction(myString);
to
myFunction(myString.toLatin1().data());
However, I have a huge code base that compiles fine with Qt 4 and I would really like to have my old code compile with Qt 5 without modifying it. Is there any way to achieve this?
You could create a macro or inline function for your purpose to minimize the changes, but since that would also require a grep alike operation, there is not much difference.
#define QString2charp(myString) myString.toLatin1().data()
or
inline char* QString2charp (const QString &myString)
{
return myString.toLatin1().data();
}
and then:
myFunction(QString2charp(myString));
BUT
of course, in an ideal world, it would be nice if your "myFunction" could get an overload expecting a QString argument.
void myFunction(const char *parameter);
void myFunction(QString parameter);
and then the overload would be implemented like this:
void myFunction(const QString ¶meter)
{
myFunction(myString.toLatin1().data());
}
of course, this would require the constructor being explicit so that no implicit conversion can happen, otherwise the compiler will complain about ambiguity in presence of both when trying to pass const char*, but if you always use QString, it should just work with Qt 5.
This is somewhat equal to rewriting the original function to a different signature expecting QString though because unfortunately the corresponding constructor is not explicit. I imagine that was not changed in Qt 5 for compatibility as it would have broken too much code.
As you can see, you do not need to change anything in your code this way, other than adding a one-liner overload. It is neat, isn't it?
You could either
Change the signature of your function to MyFunction( const QString & parameter ) (of course that works only if you don't need the one that takes char * any more)
Overload MyFunction:
void myFunction(const char *parameter); //this is your normal function
void myFunction( const QString & parameter )
{
char * c_str = nullptr;
<convert parameter to char * in any way that suits you>
myFunction( c_str );
}
If the above is impossible for some reason, the best approach is probably to write a similar wrapper:
void MyFunctionWrapper( const QString & parameter )
{
<same as above>
}
It is no longer possible to cast QString to const char* in >= Qt 5, because QString is UTF-16 and no longer has an entry for caching the result of converting to ASCII.
The way to achieve your aim is
a) Add overloads to the functions expecting const char* which can handle QStrings,
b) Add the explicit conversion code to the call-site, or
c) Go to some char-based string, like std::string.
None of those fulfill your aim of nearly no changes though.
I found this on QT forum
const QByteArray byteArray = mytext = textBox.text().toUtf8();
const char *mytext = byteArray.constData();
This resolved my issue
I recently upgraded my Intel C++ compiler from v13.0.1 (aka 2013) to v14.0.0 (aka 2013 sp1). It looks as though the standard libraries that it uses have become more C++11 compliant. As part of that, std::locale::facet was changed from:
class locale::facet {
protected:
explicit facet (size_t refs = 0);
virtual ~facet();
private:
facet (const facet&); // not defined
void operator= (const facet&); // not defined
}
To:
class locale::facet {
protected:
explicit facet (size_t refs = 0);
virtual ~facet();
facet (const facet&) = delete;
void operator= (const facet&) = delete;
}
The key piece being the use of = delete to make it non-copyable. (Thanks to http://www.cplusplus.com/reference/locale/locale/facet/ for that side-by-side comparison.)
However, boost/date_time/date_facet.hpp uses this:
class date_facet : public std::locale::facet {
That's unchanged in both boost v1.48.0 and v1.54.0 (the two that I have installed in my environment).
date_facet doesn't appear to declare any copy constructor or operator=.
In my own code, I am using it to make class static constants to hold a time format. So in a header file I have this as part of a class definition:
static const boost::local_time::local_time_facet _MYFACET;
And in the matching source file I have this:
const boost::local_time::local_time_facet MyClass::_MYFACET = boost::local_time::local_time_facet("%Y/%m/%d %H:%M:%S.%f");
This code has worked for years and is unchanged.
Now, when I try to compile I get this error:
/usr/include/boost/date_time/date_facet.hpp(49): error #373: "std::locale::facet::facet(const std::locale::facet &)" (declared at line 409 of "/usr/include/c++/4.4.6/bits/locale_classes.h") is inaccessible
class date_facet : public std::locale::facet {
^
compilation aborted for MyFile.cpp (code 2)
Googling hasn't turned up anyone else talking about this problem, which makes me think that I'm just doing something stupid.
Anyone else encountered this?
Anyone have a solution?
My only idea is to explicitly add an = delete declaration to date_facet. I'll try that and supply my own answer if it works. But I really have no idea. (Edit: this idea was a failure, so don't try it.)
The reason for your troubles is that the =delete fires at compile-time in case you try to use it. Your existing code worked because the copy-constructor was required to be accessible (which is was), but it was optimized away by copy elision. The linker, who was supposed to catch the use of the copy-ctor therefore never complained and all seemed fine. That said, you might simply change your code to
const boost::local_time::local_time_facet MyClass::_MYFACET("%Y/%m/%d %H:%M:%S.%f");
and remove the need to an accessible (or even existing) copy-ctor.
Why can not you write simply
const boost::local_time::local_time_facet MyClass::_MYFACET("%Y/%m/%d %H:%M:%S.%f");
P.S. It seems that the early version of the compiler had a bug.:)
I have the following and having difficulty resolving the error please help.
i have the following class as template definition somewhere.
template<class ConcreteHandlerType>
class SomeAcceptor: public ACE_Acceptor<ConcreteHandlerType, ACE_SOCK_Acceptor>
In some other file, i initialize this class in the constructor
class initialize {
typedef SomeAcceptor<BaseClassSomeHandler> baseAcceptor_t;
typedef SomeAcceptor<DerivedClassSomeHandler> derivedAcceptor_t;
boost::shared_ptr<baseAcceptor_t;> mAcceptor;
boost::shared_ptr<derivedAcceptor_t;> mDerivedAcceptor;
bool HandleAcceptNotification(BaseClassSomeHandler& someHandler);
initialize() : mAcceptor(0), mDerivedAcceptor(new DerivedAcceptor_t) {
mAcceptor->SetAcceptNotificationDelegate(fastdelegate::MakeDelegate(this, &initialize::HandleAcceptNotification));
}
}
Error i get is
error: no matching function for call to `boost::shared_ptr<SomeAcceptor<BaseClassSomeHandler> >::shared_ptr(int)'common/lib/boost_1_39_0/boost/smart_ptr/shared_ptr.hpp:160: note: candidates are: boost::shared_ptr<SomeAcceptor<BaseClassSomeHandler> >::shared_ptr(const boost::shared_ptr<SomeAcceptor<BaseClassSomeHandler> >&)
common/lib/boost_1_39_0/boost/smart_ptr/shared_ptr.hpp:173: notboost::shared_ptr<T>::shared_ptr() [with T = SomeAcceptor<BaseClassSomeHandler>]
I also tried overloading the function with
bool HandleAcceptNotification(DerivedClassSomeHandler& someHandler);
but because mAcceptor is of type SomeAcceptor BaseClassSomeHandler, i get this error, but to fix this.
I guess i need to cast it somehow, but how to do it?
i tried doing like below inside the constructor and it didn't work
initialize() : mAcceptor(0), mDerivedAcceptor(new DerivedAcceptor_t) {
mAcceptor = mDerivedAcceptor; // Error here
mAcceptor->SetAcceptNotificationDelegate(fastdelegate::MakeDelegate(this, &initialize::HandleAcceptNotification));
}
From your code, it looks like you want mAcceptor to be assigned NULL (0), if that is the case you don't need to initialize it at all, as the default constructor will take care of that. But, since you call a function on that (NULL) pointer immediately, its not immediately clear exactly what you want to do.
If you want mAcceptor and mDerivedAcceptor to point to the same (shared) object and assuming DerivedClassSomeHandler is derived from BaseClassSomeHandler, this is a situation where you should use boost::shared_static_cast, as described here.
There's also some good information in this apparently related question.
The error is due to the mAcceptor(0) in
initialize() : mAcceptor(0), mDerivedAcceptor(new DerivedAcceptor_t) {
mAcceptor->SetAcceptNotificationDelegate(fastdelegate::MakeDelegate(this, &initialize::HandleAcceptNotification));
}
The smart_ptr default constructor assigns the wrapped ptr to NULL, so leave out mAcceptor(0) from the initialization list.
boost::shared_ptr<SomeAcceptor<BaseClassSomeHandler> >::shared_ptr(int)
It's yelling at you that there's no constructor that accepts an int.
Just use: mAcceptor()