How to combine negation with declaration inside if-statement? - c++

When using C-style return codes to signal errors, it's pretty common to see code like this:
if (do_something()) {
do_something_else();
} else {
report_failure();
}
Sometimes, if one block is much larger than the other, you might want to reorder the "handle failure" block before the "do_something_else" block.
if (!do_something()) {
report_failure();
} else {
do_something_else();
}
(Or, when it really is C-code the codes may be such that 0 indicates success rather than failure, but let's ignore that.)
When I use C++ idioms like boost::optional or one of the proposed std::expected types, usually what I want to do is put a declaration inside the condition of the if statement:
if (auto ok = do_something()) {
do_something_else(*ok);
} else {
report_failure(ok.error());
}
I like to do this because this way, ok is strictly contained in scope, it's not visible outside the two blocks.
However, once I do it this way, I can't reorder the two branches if I want, which probably annoys me much more than it should, but still.
What I would really like is a syntax
if not (auto ok = do_something()) {
report_failure(ok.error());
} else {
do_something_else(*ok);
}
But to my knowledge that doesn't actually work.
Is there a trick to accomplish that?

C++17 will introduce this syntax:
if (auto ok = do_something(); !ok) {
report_failure(ok.error());
} else {
do_something_else(*ok);
}
Which is basically what you want.
It is in the feature-complete draft.

You can add an extra scope:
{
auto ok = do_something();
if (! ok) {
report_failure(ok.error());
} else {
do_something_else(*ok);
}
}
Personally I wouldn't add those braces as the scope should be clear from the rest of the code, if you have too much functionality in one function you should refactor the code anyways...

Alright, so here's a little class that does what you want. Dress it up however you like.
template <typename T>
struct not_optional_type: public optional <T>
{
typedef optional <T> base_type;
not_optional_type( const base_type& v ): base_type( v ) { }
operator bool () const { return !(base_type)(*this); }
T operator * () const { return *(base_type)(*this); }
};
template <typename T>
not_optional_type <T>
not_optional( const optional <T> && v )
{
return not_optional_type <T> ( v );
}
Use it as you would expect:
if (auto ok = not_optional( do_something() ))
fooey();
else
success( *ok );
I personally think the proposed if syntax modification is an abomination.

Well, a lot of dirty tricks come to mind involving macros, but, supposing you don't want to go there, here's a non-macro trick:
template <class T> class notter {
T d_t;
public:
notter(T &t) : d_t(t) {}
notter(T t) : d_t(t) {}
operator bool() { return !d_t; }
T &data() { return d_t; }
};
Now you can use it as:
if (notter<int> a = do_something()) {
report_failure();
}
else {
do_something_else(a.data());
}
This assumes that do_something returns an int. You may avoid naming the type with decltype like this:
if (notter<decltype(do_something())> a = do_something()) {
but in cases like this, that may be overkill.
You may tweak it to your needs, if, say, data() is too verbose for you, or you want just one of the constructors, or to make a more "drop-in replacement" for optional<> (as per comments from Duthomhas) or expected<> - you may employ template specialization.
Also, you can take hint from std::make_shared() and such:
template<class T> notter<T> make_notter(T t) { return notter<T>(t); }
and use it like:
if (auto a = make_notter(do_something())) {

Related

PostgreSQL C++ (pqxx) and setting value if not NULL

I have some code that looks like this:
for (const auto& query_result_row : query_result) {
my_struct.a = query_results_row["a"].as<int>();
my_struct.b = query_results_row["b"].as<string>();
// and so forth.
}
In general, there might be quite a number of fields of different types. And that's good, but if a selected field is NULL, this will throw an exception. So instead I've now written this, which is highly awkward and more than a bit error-prone:
for (const auto& query_result_row : query_result) {
if (!query_results_row["a"].is_null()) {
my_struct.a = query_results_row["a"].as<int>();
}
if (!query_results_row["ab"].is_null()) {
my_struct.b = query_results_row["b"].as<string>();
}
// and so forth.
}
Ick.
Perhaps, I thought, I could make a (templated) function that simplifies this:
for (const auto& query_result_row : query_result) {
MaybeSet(my_struct.a, query_results_row["a"]);
MaybeSet(my_struct.b, query_results_row["b"]);
// and so forth.
}
The problem here is that query_results_row["a"] is itself a templated type, and, moreover, the as() type may not be precisely the same as the my_struct type (e.g., different types of ints) and although I don't see it today, that smells like the sort of thing that some day could lead to an unintended cast.
// Doesn't work.
template <typename valueT, typename postgresFieldT>
void MaybeSet(valueT& my_struct_field, const postgresFieldT& field) {
if (!field.is_null()) {
my_struct_field = field.as<valueT>();
}
}
Any suggestions on a cleaner way to express this idea of setting things if they're not not null but not trying if they are?
For future generations: I slightly changed the problem and so arrived at a simple solution.
template <typename T>
class SetThing {
// ...
void MaybeSet(const pqxx::result::field& field) {
if (!field.is_null()) {
SetClean(field.as<T>());
}
}
template <typename asT>
void MaybeSet(const pqxx::result::field& field) {
if (!field.is_null()) {
SetClean(field.as<asT>());
}
}
// ...
}
Usage then becomes
SetThing thing;
thing.MaybeSet(query_result_row["dog"]);
thing.MaybeSet<the_cast_type>(query_result_row["complicated"]);
The second form is used for a handful of complex types (e.g., classes) that I can construct from something simple (say, an int or a string) but which isn't the base (templated) type of the SetThing.

Pattern matching in C++

I'm writing a compiler in C++ and as any compiler, it requires an extreme amount of pattern matching and dynamic casts. In languages like Rust, Haskell, and OCaml I can destruct a type easily, like:
match node {
Binary{ left, right, operator } => { .. }
_ => { .. }
}
In C++ the best I can do is:
if (auto bin = dynamic_cast<Binary*>(node)) { ... }
else if (...) { ... }
Which is really limited and ugly if you introduce smart pointers into the scene. For example if I need to match 2 things for something:
bool matched = false;
if (auto m1 = dynamic_cast<Foo*>(a)) {
if (auto m2 = dynamic_cast<Bar*>(b)) {
matched = true;
}
}
if (!matched) {
// This is because C++ does not allow you to declare two variables inside the condition...
}
I know about the Mach7 library but to be honest it seems awful as you need to write metadata for your structures (also as I've noticed it has quite a lot of bugs and limitations).
Is there a way to make these kind of matches more readable?
The following seems to be a way to avoid the double if for two matches - and can easily be generalized:
template <class T1,class T2> struct castPairstruct : public std::pair<T1,T2> {
operator bool() {return first && second;}
castPairstruct<T1,T2>(T1 a,T2 b):std::pair<T1,T2>(a,b) {;}
};
template <class T1,class T2> castPairstruct<T1,T2> castPair(T1 a,T2 b){
return castPairstruct<T1,T2>(a,b);
}
if (auto j=castPair(dynamic_cast<Foo*>(a),dynamic_cast<Bar*>(b)) {

How are template arguments expanded

I am confused about the expansion of this template [example one]. If bool b is checked at runtime in the constructor where is b stored ? is it put into the private data section [example two]? or does it become compile time and remove a branched based on the bool? or does it simply "paste" what was passed as a template argument into the if(b) [example 3]
Example one:
template<bool b>
class Test
{
public:
Test()
{
if(b)
{
// do something
}
else
{
// do something else
}
}
};
Example two:
class Test
{
public:
Test()
{
if(b)
{
// do something
}
else
{
// do something else
}
}
private:
bool b = true;
};
Example three:
//called with Test<true>
class Test
{
public:
Test()
{
if(true)
{
// do something
}
else
{
// do something else - probably removed due too compiler optimization
}
}
};
Example 3 is the snippet that more closely resembles what the compiler is doing. It's important to understand that example 2 is wrong, as the template parameter is evaluated at compile-time and not injected into the class as a field.
Doing if(b){ } else { } where b is a template bool parameter will require both branches of the if statement to be both parseable and well-formed, even if the compiler will very likely optimize out the branch that doesn't match b.
If you want guaranteed compile-time branch evaluation, and if you need only the taken branch to be well-formed, you can use if constexpr(...) in C++17:
if constexpr(b)
{
// do something
}
else
{
// do something else
}
...or implement your own static_if construct in C++14...
...or use an explicit template specialization in C++11.
I cover all of these techniques in my CppCon 2016 talk, "Implementing static control flow in C++14".

How to return a NULL from a templated method, without using a pointer

I have some code that looks like this:
template <class T>
T foo(T a) {
if (a) {
// do somethin', returns object of type T
} else {
return NULL;
}
}
But of course it won't compile since NULL is not of type T. Someone suggested this solution to me but I don't like it:
template <class T>
T* foo(T a) {
if (a) {
// do somethin', returns object of type T*
} else {
return nullptr;
}
}
I am wondering how to make this function able to return a NULL value if possible without the use of a pointer?
In C++17, you will be able to use std::optional<T>. And you could do something like this:
template <class T>
std::optional<T> foo(T a) {
if (a) {
// do somethin', returns object of type T
return std::make_optional(/*Anything that constructs `T`*/);
} else {
return {};
}
}
And on the receiving end, you can test for the value being there:
auto my_val = foo(obj);
if(my_val){
/* :-) ....knock yourself out! */
}
else{
/* :-( ....we didn't find the value */
}
For now,
You can use Boost.Optional.
Or, if you are using a very recent compiler, you may be able to access it from std::experimental::optional.
Or, if you do not want to use Boost and its dependencies, you can simply grab this tiny header (a working implementation of optional from one of the proposers of optional into the C++ standard)... It's header only, so, you only need to download/copy that single header file and #include it.
Another cool thing with C++17 is that testing for the value will now be as simple as:
if(auto my_val = foo(obj); my_val){
// ....knock yourself out!
}
You can see more of C++17 features here: What are the new features in C++17?
template <class T>
T list<T>::getData(int i){
if (i < iSize && i >= 0){
return listData[i];
} else {
cout << "Does not exist";
return {};
}
}
//it works pretty well

Struct and Tuple template parameters in D

Is it possible to write a single templated function to increment the (numeric) fields of different structs? For example:
struct Color
{
ubyte a,r,g,b;
}
struct Point
{
double x, y;
}
I tried something like this:
T update(T, A)(T t, A a)
if (is(T == struct))
{
auto vals = t.tupleof;
foreach (i; 0 .. vals.length) {
vals[i] += a; // error: i cannot be read at compile time
}
return T(vals); // convert back to struct
}
I have also tried writing function templates that accept tuples, but the tuples are always expanded, which prevents the compiler from matching the correct template.
Thanks.
Well, I'd say that what you're trying doing is rather bizarre, but it's certainly possible. The most naive, in-place way would probably be:
void update(T)(ref T t)
if(is(T == struct))
{
foreach(ref var; t.tupleof)
++var;
}
The simplest way to do it with a copy would probably be to copy it and then update it rather than trying to construct a new one with updated values (though I'm sure that that can be done too if you really want to):
T update(T)(T t)
if(is(T == struct))
{
auto copy = t;
foreach(ref var; copy.tupleof)
++var;
return copy;
}
The main problem here, of course, is that the template constraint on both of these is far too weak. All you have to do is have unincrementable types in your struct, and it won't work. The simplest way to fix that would probably be to create an eponymous template to test it for you:
T update(T)(T t)
if(isIncrementableStruct!T)
{
auto copy = t;
foreach(ref var; copy.tupleof)
++var;
return copy;
}
template isIncrementableStruct(T)
{
enum isIncrementableStruct = is(T == struct) &&
is(typeof({T t; foreach(var; t.tupleof) ++var;}));
}
And if you want to be able to increment all of the fields that are incrementable and leave the others alone, you'd probably do something like:
T update(T)(T t)
if(is(T == struct))
{
auto copy = t;
foreach(ref var; copy.tupleof)
{
static if(canIncrement!(typeof(var)))
++var;
}
return copy;
}
template canIncrement(T)
{
enum canIncrement = is(typeof({T var; ++var;}));
}
In any case, the main thing that you appear to have missed was to attempt iterating over tupleof directly while using ref so that the elements were updated rather than having copies of them being updated.