Passing empty QString by reference - c++

I have a method that has this signature
void SetFoo(QString& foo);
and I'm trying to pass an empty string inline, but none of the following compile
SetFoo("");
SetFoo(QString(""));
(error: no matching function for call to ‘MyClass::SetFoo(QString)’)
but if I create a variable like this, it works.
QString emptyFoo = "";
SetFoo(emptyFoo);
Is there not a way to call the method without creating a variable explicitly?
NOTE:
Everything seem to work in windows environment with using vc++ compiler but I encounter the above mentioned compilation error in linux environment using g++.

You can create a global object as a const QString nullStr() and use it everywhere- Somewhat similar to Null Object Pattern.
Alternatively as billz mentions, a const reference to a temporary can exist, so making it const Qstring& will enable the first 2 versions
Regardless, you should change the reference to const Qstring& if you dont intend to modify it.

To bind a reference to a temporary object, you need const qualifier, if QString constructor takes char* input, try:
void SetFoo(const QString& foo);
It makes sense to pass a reference to outlived variable to SetFoo only:
void SetFoo(QString& foo);
QString s;
SetFoo(s);
.
NOTE: Everything seem to work in windows environment with using vc++ compiler but I encounter the above mentioned compilation error in linux environment using g++.
VisualStudio is famous(good or bad way) for its C++ extentions, your code compiles on VS doesn't mean it's the C++ standards. The better way is to turn on compile warning(level 4) when you write code, it should give you a warning for binding a reference to temporary object.
Also lookup C++ standard, lookup compiler manuals to make sure your code is portable.

Related

is variable capture in lambda functions which are members of a static data structure allowed?

I got the following code snipped.
bool parseTool() {
string name;
string version;
static /*!!*/ AttrMap attrMap = {
{"name", Attr([&](const string &val)->bool{name = val;return true;})},
{"version", Attr([&](const string &val)->bool{version = val;return true;})},
};
return parseAttributes(attrMap);
}
The attrMap is declared static and lambda functions capture variables from the stack of the parseTool.
Compilation produces no errors and executable runs happily, up to some point, when it starts producing trash. Of course, removing 'static' fixes the 'trash' issue (probably making name and version static will fix it too, but i have not tried it). I do not understand what does compiler capture in this case when the static attrMap is initialized.
The question is, why did not compiler complain about it? Is there anything in the standard which would mark this case (I could not find one)? What does compiler do there?
I was running gcc-7.2.8 with -std=c++17 on linux.
The compiler has no way of knowing that the references you are capturing will no longer be valid the next time the lambda is called or even if the lamda will ever be called again.
The code you have posted is dangerous and likely to fail but is perfectly valid according to the standard so the compiler is free to accept it without warnings.
To fix it capture the variables by value or make the lambda not static. Making the lambda static probably doesn't make much sense as creating a lambda probably isn't expensive in most implementations and depending how the lambda is used may be inlined away completely.

Why has assignment to a gr_complex variable (GNU Radio) stopped working for me?

In the block definition for my custom SDR transceiver hardware I use the following complex variable:
gr_complex complexSample;
In my code, which has worked successfully for two years before a recent upgrade to the latest gnuradio release, I use the following assignments:
complexSample.real() = realInt;
complexSample.imag()= imagInt;
However, when I try to compile now, I get the following error:
error: lvalue required as left operand of assignment
Frustratingly, if I remove the pair of parentheses, I get the following error:
error: invalid use of member function 'void
std::complex::imag(float)' (did you forget the '()'? )
The original version of gnuradio I have been using is 3.7.5-5, and the latest I have upgraded to is: 3.7.10.1-2.
Has something significant changed between these two releases which could explain this difference in behaviour?
If so, what is the solution?
Could this be something to do with 'Volk integration' (whatever that is...).
No, GNU Radio didn't change gr_complex. It's still but an alias for std::complex<float>.
What probably has changed is that you're now using a compiler set to C++14, and that makes std::complex<float>.real() return a const that you can't assign to. (I think that's what happens.)
You should either just construct the value like you mean to, i.e.
gr_complex foo(realpart, imagpart)
or use the setters
gr_complex foo;
foo.real(realpart);
foo.imag(imagpart);
As the error message shows, gr_complex is a typedef for std::complex<float>. That means the .real() and .imag() methods are getters, not setters.
That's not what you want anyway. You just want to assign the number, not its separate components: complexSample = gr_complex{realInt, imagInt}.

Different boost version causing failure in boost/core/ref.hpp due to deleted function

I have switched my boost version and I am trying to recompile my code but I get the following error:
/boost/core/ref.hpp:179: error: deleted function ‘void boost::cref(const T&&) [with T = const char*]’
It is for this specific line here:
// find file prefix with matching system type in systemtype attribute
pugi::xml_named_node_iterator xmniFilePrefix = std::find_if(xmnrFilePrefixes.begin(),xmnrFilePrefixes.end(),
boost::bind(std::equal_to<std::string>(),
boost::bind(PUMLinux::Functions::ObtainAttributeValue, _1, boost::cref(PUMLinux::Configuration::SYSTEMTYPE.c_str())),
c_strSystemType));
Anyone know what I can do to resolve the issue with the new boost I'm using?
You can not do this, boost is exactly correct in doing so. You are taking cref() to the temporary, but cref is nothing more than a fancy wrapping around the pointer.
So you are trying to get an address to the temporary object returned by c_str(), and this is no-no-no.
However, since it seems to be static, unchanged string SYSTEMTYPE, you can get away by completely eliminating boost::cref - pass the return value of c_str() directly. You might need to change the signature of your ObtainAttributeValue to receive pointer.

Code::blocks complaining about type of parameter

I am building a 3D Game Engine. I have build many in other languages, but finally decided to reap the speed benefits of C++ (despite not knowing it particularly well).
I have a class called EngineOptions that I use to store information about how the engine is to be initialized. The engine's main class, Monolith, then takes a const reference to the options instance like so:
monolith::EngineOptions options();
monolith::Monolith engine(options);
Monolith has a correct header file and a constructor like this:
Monolith::Monolith(const EngineOptions& options) : m_options(options)
{
m_window(m_options.windowWidth, m_options.windowHeight, m_options.windowTitle);
}
While I think this is correct, the compiler is complaining that there is:
no matching function for call to 'monolith::Monolith::Monolith(monolith::EngineOptions (&)())'
Excuse me if I'm being stupid, but I think this code is correct, am I wrong?
I am using the Code::Blocks IDE with the standard GCC toolchain provided on my system.
Remove the parentheses from this line:
monolith::EngineOptions options();
The compiler thinks you're declaring a function returning an EngineOptions instance.

Error C2668 in bind while porting from VS2008 to VS2013

I'm trying to port my code from VS2008 to VS2013 and I'm getting some errors with std::bind.
The errors say error C2668: 'bind' : ambiguous call to overloaded function.
Here's some code:
// Relevant prototypes:
class CLineaPlanta:public SomeBase { /*...*/ };
int SomeBase::TipoLinea()const;
void SomeBase::TipoLinea(int val);
// function paramater: const std::shared_ptr<CLineaPlanta>& lineasBuscar
// function parameter: int tipoLinea;
std::shared_ptr<CLineaPlanta> lineas;
std::remove_copy_if(lineasBuscar.begin(), lineasBuscar.end(),
std::back_inserter(lineas),
bind(std::not_equal_to<int>(), bind(&CLineaPlanta::TipoLinea, _1), tipoLinea));
This code worked in Visual Studio 2008, but gives the mentioned error in Visual Studio 2013.
Obviously, the compiler's having a hard time figuring out which version of TipoLinea() I'm trying to call. If I rename the getter version to getTipoLinea, the error goes away.
Just in case it is relevant, SomeBase is non-abstract and derives from CObject (not really sure why) and from an interface not related to this part of the code.
Can anyone explain why VS2008 doesn't have any problem with this and how to prevent it (other than by renaming the function, of course)?
I have no idea why this code ever worked in VS2008. It was probably a consequence of 2008's bind being implemented as a macro-based variadics emulation where bind had several overloads for each number of arguments being passed, one of them expecting the first argument to be a pointer to member function with the same number of arguments. This would allow the compiler to disambiguate because you pass one bound argument to bind, so it knows the function argument must have one parameter.
In VS2013, true variadics are used, but this probably means that the type of the first argument is more generic and so the compiler can no longer disambiguate. To make this compile, you need to explicitly cast the member pointer:
std::remove_copy_if(lineasBuscar.begin(), lineasBuscar.end(),
std::back_inserter(lineas),
bind(std::not_equal_to<int>(),
bind(static_cast<int (SomeBase::*)() const>(&CLineaPlanta::TipoLinea),
_1),
tipoLinea));
But as Neil Kirk said, rewriting to a lambda is easier:
std::remove_copy_if(lineasBuscar.begin(), lineasBuscar.end(),
std::back_inserter(lineas),
[tipoLinea](const std::shared_ptr<CLineaPlanta>& linea) {
return linea->TipoLinea() != tipoLinea;
});