ternary operator doesn't work with lambda functions - c++

I am assigning to a std::function<double()> a lambda expression. This snippet works
if(fn_type==exponential)
k.*variable = [=,&k](){ return initial*exp(-k.kstep*par); };
else
k.*variable = [=,&k](){ return initial*pow(k.kstep, par); };
whereas if I want to use the ternary operator
k.*variable = (fn_type==exponential ? [=,&k](){ return initial*exp(-k.kstep*par); } : [=,&k](){ return initial*pow(k.kstep, par); });
I get the following error:
error: no match for ternary ‘operator?:’ in <awfully long template error, because this whole thing is in a class defined in a function...>
Is this a gcc bug (I'm using 4.7.2)? Otherwise why is there this limit in the standard?

The second and third operands of the conditional operator must have the same type or there must be some common type to which they can both be converted that the compiler can figure out. There are only a handful of conversions that the compiler will consider.
Your two lambda expressions have different types, and there is no common type to which they can both be converted (conversions to user-defined types, like std::function<double()>, cannot be considered because there are potentially an infinite number of valid target types).
You can directly convert each of the operands to std::function<double()>:
k.*variable = fn_type==exponential
? std::function<double()>([=,&k](){ return initial*exp(-k.kstep*par); })
: std::function<double()>([=,&k](){ return initial*pow(k.kstep, par); });
But really, it's cleaner with the if/else.

Also faced this issue - won't compile!
'if/else' not good for me, I would like auto type deducing feature turn on.
auto memcpy_traits =
[&](uint8_t* line_dst, const uint8_t* curr_src, const size_t bytes_to_copy) {
std::memcpy(line_dst, curr_src, bytes_to_copy);
line_dst += bytes_to_copy;
curr_src += bytes_to_copy;
}
:
[&](uint8_t* line_dst, const uint8_t* curr_src, const size_t bytes_to_copy) {
std::memcpy(line_dst, curr_src, bytes_to_copy);
line_dst += bytes_to_copy;
curr_src += bytes_to_copy;
};

Related

Invoke user-defined literal on lvalue

Is there any way to invoke a user defined literal on lvalues?
e.g I would like to
int operator "" _xor1(int a) { return a^1; }
// Works fine
17_xor1;
auto myint = get_something_only_availabe_at_runtime();
// Any way to use _xor1 on myint?
_xor1(myint); // Doesn't work
Also, when compiling the following code at the compiler explorer, I was surprised to discover that it was all resolved at runtime, although all data is available at compile time. Why is that?
constexpr int operator "" _xor1(unsigned long long a) {
return a^1;
}
int main() {
// This code resolves the user defined literal at runtime on gcc,
// msvc and clang - I don't see why I can't use the
// user defined literal at runtime?
return 17_xor1;
}
I'm not sure you really want to - as commented, you're probably better off defining a normal function and calling that - but you can call it using:
operator""_xor1(myInt);
See User-defined literals for more information.
No, you cannot invoke a user-defined literal on a variable populated at runtime. Nor do you need to. Just define a standalone function that different pieces of code can invoke when needed, eg:
template <typename T>
T do_xor1(T a) { return a^1; }
int operator "" _xor1(unsigned long long a) { return do_xor1(a); }
// Works fine
17_xor1;
auto myint = get_something_only_availabe_at_runtime();
do_xor1(myint);

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.

Write method with trailing return type to change based on method call?

I have a class titled Eclipse with a private struct member containing ~30 fields of various data types.
I have a method that will return a data field from the struct, based on a field number passed in as a parameter.
Seeing as the struct contains data of various types, I opted to use the auto keyword with a trailing return type based on a templated parameter. My method header is below.
template<typename TheType>
auto getColumnData(TheType toGet, int fieldNum) -> decltype(toGet) {
// switch statement to return fields based on fieldNum
}
If I want to return a column that is an int, I call getColumnData(0, 1);. The first parameter is only used to determine the return type of the method, and the second parameter determines the field number to return to the method caller.
Theoretically, this would cause the return type of getColumnData() to be int and return the first column (corresponding to the first field) of the struct. But I'm receiving this compilation error:
no viable conversion from returned value of type 'std::string' (aka 'basic_string<char, char_traits<char>, allocator<char> >') to function return type 'decltype(toGet)' (aka 'int')`
I understand that if I were to call this method with an int as the first parameter, and a field number that corresponds to a field returning a std::string, there would be issues. But, based on checks in other classes, this case would never occur.
Is there any way that I can force my compiler to accept this code, even if it might not be correct for certain cases?
I know that I could just overload the method, but I'd rather not have multiple different methods for basically the same purpose if I can figure out how to accomplish the task in only one.
Also, if my understanding of any of this information seems incorrect, please let me know. I'm very new to C++, so I'm just learning these features as I go.
You cannot change a method's return type dynamically at runtime like you are attempting to do. Your first parameter is not a data type known at compile-time. It is just an integer that is populated at runtime, so you can't make compile-time decisions based on it at all.
A simple solution would be to use std::variant (C++17 or later) or boost::variant (C++11 and later) as the return type:
using FieldType = std:::variant<int, std::string>;
FieldType getColumnData(int fieldNum) {
// switch statement to return fields based on fieldNum
}
int i = std::get<int>(getColumnData(1));
std::string s = std::get<std::string>(getColumnData(2));
Otherwise, you would have to make the return type be a template parameter, not a method parameter:
template<typename TheType>
TheType getColumnData(int fieldNum) {
// switch statement to return fields based on fieldNum
}
But then you run into the problem that not all fields will be convertible to the return type (can't return a std::string field when an int is requested, etc), so you can't just switch on the fieldNum since it is not evaluated at compile-time.
You might be tempted to make the field number be a template parameter so it is constant at compile-time, and then specialize on it:
template<const int FieldNum>
auto getColumnData() { return 0; };
template<> int getColumnData<1>() { return private_struct.Field1; }
template<> std::string getColumnData<2>() { return private_struct.Field2; }
// etc...
int i = getColumnData<1>();
std::string s = getColumnData<2>();
But I get errors when I try to do that on a templated class method ("explicit specialization in non-namespace scope").
You might be tempted to do something like this, and hope the compiler optimizes away the unused branches:
template<const int FieldNum>
auto getColumnData() {
if (FieldNum == 1) return private_struct.Field1;
if (FieldNum == 2) return private_struct.Field2;
//etc...
return 0;
}
or
template<const int FieldNum>
auto getColumnData()
{
switch (FieldNum) {
case 1: return private_struct.Field1;
case 2: return private_struct.Field2;
// etc...
}
return 0;
};
int i = getColumnData<1>();
std::string s = getColumnData<2>();
But that doesn't work, either ("inconsistent deduction for auto return type" errors).

Defining const "variable" inside if block

I have the following code:
Foo a;
if (some_fairly_long_condition) {
a = complicated_expression_to_make_foo_1();
} else {
a = complicated_expression_to_make_foo_2();
}
I have two issues with this:
a is a const and should be declared so
the "empty" constructor, Foo() is called for no reason (maybe this is optimised away?)
One way to fix it is by using the ternary operator:
const Foo a = some_fairly_long_condition?
complicated_expression_to_make_foo_1():
complicated_expression_to_make_foo_2();
Is this good practice? How do you go about it?
To answer the second part of your question:
I usually put the initialization code into a lambda:
const Foo a = [&]()->Foo{
if (some_fairly_long_condition) {
return complicated_expression_to_make_foo_1();
} else {
return complicated_expression_to_make_foo_2();
}
}();
In most cases you should even be able to omit the trailing return type, so you can write
const Foo a = [&](){ ...
As far as the first part is concerned:
I'd say that greatly depends on how complex your initialization code is. If all three parts are really complicated expressions (and not just a function call each) then the solution with the ternary operator becomes an unreadable mess, while the lambda method (or a separate named function for that matter) allows you to break up those parts into the respective sub expressions.
If the problem is to avoid ternaty operator and your goal is to define the constant a, this code is an option:
Foo aux;
if (some_fairly_long_condition) {
aux = complicated_expression_to_make_foo_1();
} else {
aux = complicated_expression_to_make_foo_2();
}
const Foo a(aux);
It is a good solution, without any new feature ---as lambdas--- and including the code inline, as you want.

Can I make the ternary operator treat my class like a bool?

I've recently been doing a huge refactoring where I was changing a lot of my code to return booleans instead of an explicit return code. To aid this refactoring I decided to lean on the compiler where possible by getting it to tell me the places where my code needed to be changed. I did this by introducing the following class (see here for the lowdown on how this works):
///
/// Typesafe boolean class
///
class TypesafeBool
{
private:
bool m_bValue;
struct Bool_ {
int m_nValue;
};
typedef int Bool_::* bool_;
inline bool_ True() const { return &Bool_::m_nValue; }
inline bool_ False() const { return 0; }
public:
TypesafeBool( const bool bValue ) : m_bValue( bValue ){}
operator bool_() const { return m_bValue ? True() : False(); }
};
Now, instead of using a normal bool type as the return type, I used this class which meant that I couldn't compile something like this any more:
TypesafeBool SomeFunction();
long result = SomeFunction(); // error
Great: it has made the refactoring manageable on a huge codebase by letting the compiler do a lot of the hard work for me. So now I've finished my refactoring and I'd quite like to keep this class hanging around and carry on using it since it affords us an extra level of safety that the built-in bool type doesn't.
There is however one "problem" which is preventing me from doing this. At the moment we make heavy use of the ternary operator in our code, and the problem is that it is not compatible with this new class without explicit casts:
TypesafeBool result = ( 1 == 2 ? SomeFunction() : false ); // error: different types used
TypesafeBool result = ( 1 == 2 ? SomeFunction() : (TypesafeBool)false );
If I could "solve" this issue so that I could use my class in a seamless manner I would probably carry on using it throughout the codebase. Does anyone know of a solution to this issue? Or is it just impossible to do what I want?
In the context of the conditional operator, the type of the expression is the common type of the last two operands. The complete rules to determine this common type are a bit complex, but your case happens to be trivial: if one of the two possible return values is a class type, the other value must have the same class and the common type is obviously also that class.
That means that if one of the operands is a TypesafeBool, then the other must be as well.
Now the problem you're really trying to solve has been solved before. The trick is not providing a class; instead use a typedef. See for instance safe bool.
class CCastableToBool
{
public:
// ...
operator bool() const
{
//...
{
return true;
}
//...
return false;
}
private:
// ...
};
but beware, in C++ it is considered really dangerous to have a class that can be casted to bool. You are warned :-)
you can read this there, SafeBool
You should explicitely call TypesafeBool::True() in all your ternary tests.
TypesafeBool result = ( 1 == 2 ? SomeFunction().True() : false );
I don't know about a seamless manner, the ternary operator has some restrictions on its use...
However, why don't you define two constants ?
TypesafeBool const True = TypesafeBool(true);
TypesafeBool const False = TypesafeBool(false);
And then:
TypesafeBool result = ( 1 == 2 ? SomeFunction() : False );
Of course, it's a bit unorthodox since I play on the capitalization to avoid reusing a reserved word :)
Is it a possibility to make the constructor of TypesafeBool explicit? Of course, now the usage has to be
TypesafeBool result( 1 == 2 ? b : false );
Could you use an assignment operator that takes in a bool as the external argument, as well as one that takes a TypesafeBool? It might be something to try out...
Nice try, but if your code base is large, you are probably better off using a static checker such as PC-Lint to look for implicit bool<->int conversions instead.