boost spirit semantic action requirements - c++

Given the following actions
struct Data {
double d;
void operator()( double dd,
boost::spirit::qi::unused_type,
boost::spirit::qi::unused_type )
{ d = dd; }
};
struct Printer {
void operator()( double dd,
boost::spirit::qi::unused_type,
boost::spirit::qi::unused_type ) const
{ std::cout << dd; }
};
the code
void foo( const std::string &s ) {
Printer p;
boost::spirit::qi::parse( s.begin(), s.end(),
boost::spirit::qi::double_[ p ] );
}
does compile while
double foo( const std::string &s ) {
Data d;
boost::spirit::qi::parse( s.begin(), s.end(),
boost::spirit::qi::double_[ d ] );
return d.d;
}
does not.
Looking at the examples in http://www.boost.org/doc/libs/1_53_0/libs/spirit/doc/html/spirit/qi/tutorials/semantic_actions.html, one sees that the function objects use a operator() declared const. The error message C3848 of MSVC suggests something similar.
Is constness required here? The documentation in http://www.boost.org/doc/libs/1_53_0/libs/spirit/doc/html/spirit/qi/reference/action.html only says the signature void( Attrib&, Context, bool& ) is required.
Remark: I must admit I don't really understand the sentence
The function or function object is expected to return the value to
generate output from by assigning it to the first parameter, attr.
in this context.

Q.2: Remark: I must admit I don't really understand the sentence
A. You could look at boost spirit semantic action parameters for indepth explanation of it. Here is the short version:
void action_f(std::string& attribute,
qi::unused_type const& context,
bool& flag)
{
boost::fusion::at_c<0>(context.attributes) = "hello world"; // return the attribute value
flag = true; // signal parse success
}
Q.1: Is constness required here? The documentation in http://www.boost.org/doc/libs/1_53_0/libs/spirit/doc/html/spirit/qi/reference/action.html only says the signature void( Attrib&, Context, bool& ) is required.
A. The const-ness may not be explicitely required by the library, however the requirement is implicitely introduced by the C++ language due the way you are using the parser expression1:
The expression template
boost::spirit::qi::double_[ d ]
yields a temporary, which when passed to the qi::parse API can only get bound to a const reference2,3. This is where the 'const' on the whole parser expresion is introduced, and it extends equally to members of the subexpression(s), such as those that store the semantic action, d.
Therefore the instance of d at the time of deferred invocation will be logically const and therefore the operator() will not be selected, whereas operator() const will.
1. Upon more thought, it doesn't really depend on how you use it. The logic of my explanation is sound, but because spirit even supports inline parser expressions, call()-ing parsers is necessarily a const member operation on that parser, and as such all other operations will be in const context anyway. And indeed, in boost::spirit::traits::action_dispatch::operator() you'll see the calleables being passed as F const&, e.g. reflecting this.
2. Spirit V2 does not support move semantics for rules - nor, indeed, does it require them
3. The lifetime of the temporary will be extends to the end of the containing full expression, as per standardese

Related

Reuse of variable of type auto

I have a special class to be used as return type of methods, containing the wanted value or in case of failure an error message which is even cascading from earlier errors. It works as expected.
As the returned type is differently complex I like to use the keyword auto. But when using a lot of methods I have to create new return variables.
A typical part of code looks like this:
auto ret1 = methodA();
if(ret1.isValid()...
auto ret2 = methodB();
if(ret2.isValid()...
I dont like to always create a new variable. But I like the elegant way of error handling. Using a more dump return type like an error code in integer would solve the problem but then I have no benefit from the error handling return type.
Is there any trick to reuse the first return variable ret1?
You would have to create new scopes to reuse the variable name for a different variable, like:
{
auto ret = methodA();
if (ret.isValid()) ...
}
{
auto ret = methodB();
if (ret.isValid()) ...
}
You can also take advantage of the scope created by if, placing the init-statement inside:
if (auto ret = methodA(); ret.isValid()) ...
if (auto ret = methodB(); ret.isValid()) ...
auto is not a type.
It is a keyword, that says "put the type here for me, by deducing it from the initial value". That occurs during compilation, once.
You cannot reuse ret1 to store an object of a different type, whether you use auto or not.
This shouldn't really be a problem. If you're concerned about "running out of names", or "having many similar names", your names are not descriptive enough and/or your scopes aren't tight enough.
auto is not a type. In auto foo = bar(); the compiler simply figures out what type bar() actually returns and substitutes that in. So if bar() returns int then that's the type of foo, if it returns bool then that is the type of foo. And once the type that auto should be replaced with (the first time) has been determined, then it can never change. auto doesn't mean "variable type" it just means "hey compiler, I'm too lazy to figure out the type to put here, please do it for me", but there is no difference what-so-ever compared to you just writing the final type yourself.
So, you can reuse the variable if what you assign to it the second time is of the same type as the first time - otherwise not.
I dont like to always create a new variable.
Much better is to create a const variable:
const auto ret1 = methodA();
if(ret1.isValid()...
const auto ret2 = methodB();
if(ret2.isValid()...
In this case you need to make const all the methods like isValid, but that is even better: "is" shouldn't have side effects and modify the state.
Next step is to remove the temp variable at all:
if(methodA().isValid()) {
...
}
if(methodB().isValid()) {
...
}
The alternative is to wrap each function call into a block:
{
const auto ret = methodA();
if(ret.isValid()...
}
{
const auto ret = methodB();
if(ret.isValid()...
}
This allows you to reuse the const variable name.
Each block becomes a candidate for extraction into a separate function (see Uncle Bob in "Clean Code").

Void function doing return (void)(something)

I saw a few functions in an SDK I'm using do something similar to the following:
void foo( float& fl )
{
if ( std::isnan( fl ) || std::isinf( fl ) )
return ( void )( fl = 0.f );
/*...*/
}
Why?
Why?
On the face of it, someone was just being "clever". You see, there are restrictions placed on a return statement in C++
[stmt.return]
2 The expr-or-braced-init-list of a return statement is called its
operand. A return statement with no operand shall be used only in a
function whose return type is cv void, a constructor, or a
destructor. A return statement with an operand of type void shall be
used only in a function whose return type is cv void. A return
statement with any other operand shall be used only in a function
whose return type is not cv void; [...]
The above makes a simple return ( fl = 0.f ); in that function illegal. Because the expression ( fl = 0.f ) (the return statement's operand) is not of type void. But the author of that function, maybe in an effort to conserve lines of code, or to express some sort of "elegance", decided to force the issue. Since an operand of type void is okay, they added a cast. That's not the only way to make the compiler submit, for instance:
return fl = 0.f , void();
That makes use of the comma operator, and the void() prvalue. It's not code I'd personally advocate one to write. The code in your post and this alternative are unidiomatic, confusing and misguided. Braces ({}) would have made that function much clearer. So while I hope you learned something about C++ from this, don't get in the habit of writing such code. Your colleagues will think more highly of you if you write code they can understand at a glance.
return ( void )( fl = 0.f );
Why?
That is rather unusual code. Casting an expression to void is usually done to suppress a compiler-warning -- it's an idiom that tells the compiler "yes, I know I am throwing this expression's value away -- but I'm doing it deliberately, so you don't need to warn me about it".
What is unusual there is that the author decided to do that in a return statement. It would have been clearer (and logically equivalent) to write
{
fl = 0.0f;
return;
}
instead. The only thing I can think of is that the function used to return a value, and perhaps the author thought he might someday want to change it to return a value again, and would therefore try to keep the code-style looking similar to that of a value-returning function? (If so, it seems a bit "too clever" to me)
It's the same as
void foo( float& fl )
{
if ( std::isnan( fl ) || std::isinf( fl ) )
{
fl = 0.f;
return;
}
/*...*/
}
there is no special reason to prefer one way than another.

Is there a way to make a function have different behavior if its return value will be used as an rvalue reference instead of an lvalue?

I have a routine that does some moderately expensive operations, and the client could consume the result as either a string, integer, or a number of other data types. I have a public data type that is a wrapper around an internal data type. My public class looks something like this:
class Result {
public:
static Result compute(/* args */) {
Result result;
result.fData = new ExpensiveInternalObject(/* args */);
return result;
}
// ... constructors, destructor, assignment operators ...
std::string toString() const { return fData->toString(); }
int32_t toInteger() const { return fData->toInteger(); }
double toDouble() const { return fData->toDouble(); }
private:
ExpensiveInternalObject* fData;
}
If you want the string, you can use it like this:
// Example A
std::string resultString = Result::compute(/*...*/).toString();
If you want more than one of the return types, you do it like this:
// Example B
Result result = Result::compute(/*...*/);
std::string resultString = result.toString();
int32_t resultInteger = result.toInteger();
Everything works.
However, I want to modify this class such that there is no need to allocate memory on the heap if the user needs only one of the result types. For example, I want Example A to essentially do the equivalent of,
auto result = ExpensiveInternalObject(/* args */);
std::string resultString = result.toString();
I've thought about structuring the code such that the args are saved into the instance of Result, make the ExpensiveInternalObject not be calculated until the terminal functions (toString/toInteger/toDouble), and overload the terminal functions with rvalue reference qualifiers, like this:
class Result {
// ...
std::string toString() const & {
if (fData == nullptr) {
const_cast<Result*>(this)->fData = new ExpensiveInternalObject(/*...*/);
}
return fData->toString();
}
std::string toString() && {
auto result = ExpensiveInternalObject(/*...*/);
return result.toString();
}
// ...
}
Although this avoids the heap allocation for the Example A call site, the problem with this approach is that you have to start thinking about thread safety issues. You'd probably want to make fData an std::atomic, which adds overhead to the Example B call site.
Another option would be to make two versions of compute() under different names, one for the Example A use case and one for the Example B use case, but this isn't very friendly to the user of the API, because now they have to study which version of the method to use, and they will get poor performance if they choose the wrong one.
I can't make ExpensiveInternalObject a value field inside Result (as opposed to a pointer) because doing so would require exposing too many internals in the public header file.
Is there a way to make the first function, compute(), know whether its return value is going to become an rvalue reference or whether it is going to become an lvalue, and have different behavior for each case?
You can achieve the syntax you asked for using a kind of proxy object.
Instead of a Result, Result::compute could return an object that represents a promise of a Result. This Promise object could have a conversion operator that implicitly converts to a Result so that "Example B" still works as before. But the promise could also have its own toString(), toInteger(), ... member functions for "Example A":
class Result {
public:
class Promise {
private:
// args
public:
std::string toString() const {
auto result = ExpensiveInternalObject(/* args */);
return result.toString();
}
operator Result() {
Result result;
result.fData = new ExpensiveInternalObject(/* args */);
return result;
}
};
// ...
};
Live demo.
This approach has its downsides though. For example, what if, instead you wrote:
auto result = Result::compute(/*...*/);
std::string resultString = result.toString();
int32_t resultInteger = result.toInteger();
result is now not of Result type but actually a Result::Promise and you end up computing ExpensiveInternalObject twice! You can at least make this to fail to compile by adding an rvalue reference qualifier to the toString(), toInteger(), ... member functions on Result::Promise but it is not ideal.
Considering you can't overload a function by its return type, and you wanted to avoid making two different versions of compute(), the only thing I can think of is setting a flag in the copy constructor of Result. This could work with your particular example, but not in general. For example, it won't work if you're taking a reference, which you can't disallow.

In C++17 can an if statement with an initializer be used to unpack an optional?

I'm writing some code using std::optional's and am wondering if C++17's 'if statements with initializers' will be able to help unpack values?
std::optional<int> optionalInt = GetOptionalInt();
I'm making up the function Unpack here:
if( auto [value, has_value] = optionalInt.Unpack(); has_value )
{
// Use value here.
}
But, my question is. Will C++17 'if statement with initializer' help here? If so, how would it be coded?
Update, this is actually mainly an issue when using optional which is extremely easy to misuse because the optional and *optional both return bools and you don't get any compiler warning when somebody trys to access the value and forgets the *.
There is not, and cannot possibly be, such an Unpack() function.
But you could certainly do:
if (std::optional<int> o = GetOptionalInt(); o) {
// use *o here
}
though the extra o check is kind of redundant.
This is one of those places where it'd be nice if optional<T> modeled a container of at most one element, so that you could do:
for (int value : GetOptionalInt()) {
// possibly not entered
}
but we don't have that interface.
In order for this to work, there has to be a value for the unpacked value if it isn't there.
So
template<class T, class U>
std::pair< T, bool > unpack_value( std::optional<T> const& o, U&& u ) {
return { o.value_or(std::forward<U>(u)), (bool)o } )
}
would do what you wanted.
But as an optional already returns if it is engaged in a bool context you really should just:
if (auto i = get_optional())
then use *i within the body.
...
Now if optional stated that operator* returned a reference, and that return value was defined but accessing it was not defined when it was not engaged, then you could write an Unpack method or function that doesn't require a default value.
As far as I am aware this is not true. And as it doesn't really add anything, I don't see why it should be true.
Maybe this would work:
auto optValue = getOptional();
if (auto value = *optValue; optValue) { ...use value here... }

Inject additional data in a method

I am adding the new module in some large library. All methods here are implemented as static. Let me briefly describe the simplified model:
typedef std::vector<double> TData;
double test ( const TData &arg ) { return arg ( 0 ) * sin ( arg ( 1 ) + ...;}
double ( * p_test ) ( const TData> &arg) = &test;
class A
{
public:
static T f1 (TData &input) {
.... //some computations
B::f2 (p_test);
}
};
Inside f1() some computations are performed and a static method B::f2 is called. The f2 method is implemented by another author and represents some simulation algorithm (example here is simplified).
class B
{
public:
static double f2 (double ( * p_test ) ( const TData &arg ) )
{
//difficult algorithm working p_test many times
double res = p_test(arg);
}
};
The f2 method has a pointer to some weight function (here p_test). But in my case some additional parameters computed in f1 for test() methods are required
double test ( const TData &arg, const TData &arg2, char *arg3.... ) { }
How to inject these parameters into test() (and so to f2) to avoid changing the source code of the f2 methods (that is not trivial), redesign of the library and without dirty hacks :-) ?
The most simple step is to override f2
static double f2 (double ( * p_test ) ( const TData &arg ), const TData &arg2, char *arg3.... )
But what to do later? Consider, that methods are static, so there will be problems with objects.
Updated question
Is it possible to make a pointer to a function dependent on some template parameter or do something like that
if (condition) res = p_test(arg);
else res = p_test2(arg, arg2, arg3);
without dirty hacks
Not gonna happen. If you can't modify the source of a function taking a function pointer, you'll have to use an exception vomit to gain the extra arguments. If you had a C++11 compiler (that does not exist yet) which supports thread_local, it's theoretically possible to do something better, or you could use OS-specific TLS. But as of right now, the only portable solution is an exception vomit.
void f(void(*fp)()) { fp(); }
void mah_func() {
try {
throw;
} catch(my_class* m) {
m->func();
}
}
int main() {
my_class m;
try {
throw &m;
} catch(my_class* p) {
f(mah_func);
}
}
Alternatively, in your scenario, modifying f2 doesn't seem to be impossible, only difficult. However, the difficulty of altering it to take a std::function<double(const TData&)> would be very low- all you'd have to do is change the argument type, thanks to operator overloading. It should be a very simple change for even a complex function, as you're only changing the type of the function parameter, all the call sites will still work, etc. Then you can pass a proper function object made through bind or a lambda or somesuch.
"avoid changing", well that's a bit difficult.
however, you can use a static variable to pass arguments across calls of functions that don't pass the arguments.
remember that if there is more than one thread using those function, you need to either use thread local storage (which is what i recommend for that) or else ensure proper mutual exclusion for use of those variables, where in the case of a single variable shared between all the threads means exclusion all the way down the call chain. but do use thread local storage if threading is a problem. and if no threading problem, well, no problem! :-)