How to use if-constexpr without repeating code? - c++

Currently I am doing:
if constexpr(constexpr_bool_var1) {
auto arg1 = costly_arg1(); auto arg2 = costly_arg2();
if (costly_runtime_function(arg1, arg2)) {
// do X, possibly more constexpr conditions
// do Y
// ...
}
} else {
// do X, possibly more constexpr conditions
// do Y
// ...
}
One possible way is to convert the do X/Y etc. to one function doXY() and call it in both places, however it seems very unwieldy, as I have to write a function that solely exists for convenience of meta programming.
What I want is something like:
if not constexpr(constexpr_bool_var1 && some_magic(costly_runtime_function(arg1, arg2)) {
// do X, do Y
}
Another way is:
auto arg1 = costly_arg1(); // Unneeded extra work out not within constexpr
auto arg2 = costly_arg2();
if (constexpr_bool_var1 && costly_runtime_function(arg1, arg2)) {
} else {
// do X, possibly more constexpr conditions
// do Y
// ...
}
However here arg1 and arg2 are being declared outside the if condition so they will be needlessly instantiated.

I’m not sure I understand your question correctly; your original code and your second alternative don’t express quite the same function (the meaning of costly_runtime_function is reversed from “do X and Y” to “don’t do X and Y”), and in your first propoed alternative I don’t understand what your proposed syntax or what some_magic is. I’m answering your question with the semantics of your original code sample.
The best way to handle this is probably with a flag for whether or not to do X and Y:
bool do_x_y = true;
if constexpr(constexpr_bool_var1) {
// Maybe we don't actually want X and Y
auto arg1 = costly_arg1(); auto arg2 = costly_arg2();
do_x_y = costly_runtime_function(arg1, arg2);
}
if (do_x_y) {
// do X, possibly more constexpr conditions
// do Y
// ...
}
Note that, as Andrei R. points out in the comments, the compiler can probably handle the optimization anyway. This makes it clearer to a human reader that you want this handled at compile time, though.

Here's one way. Whether it's more expressive/maintainable I cannot say.
#include <cstdlib>
#include <utility>
/*
* simulation
*/
void doX() {}
void doY() {}
int costly_arg1() { return 1; }
int costly_arg2() { return 2; }
bool costly_runtime_function(int, int) { return rand() < RAND_MAX / 2; }
constexpr bool constexpr_bool_var1 = true;
/*
* A functor that maybe does something
*/
template<class F>
struct maybe_do
{
constexpr maybe_do(F&& f) : f(std::move(f)) {}
constexpr void operator()() const
{
if (enabled)
f();
}
constexpr void enable(bool e) {
enabled = e;
}
F f;
bool enabled = true;
};
int main()
{
auto thing = maybe_do{
[] {
doX();
doY();
}
};
if constexpr(constexpr_bool_var1)
{
thing.enable(costly_runtime_function(costly_arg1(),
costly_arg2()));
}
thing();
}

You could use a lambda for that:
auto stuff = [&] {
// do X, possibly more constexpr conditions
// do Y
// ...
};
if constexpr(constexpr_bool_var1) {
auto arg1 = costly_arg1(); auto arg2 = costly_arg2();
if (costly_runtime_function(arg1, arg2)) {
stuff();
}
} else {
stuff();
}
And if your lambda can receive auto values, you could also pass variable of different types from inside the if scope.

Related

How best to test and unwrap std::optional in an if statement

I have multiple functions that return a std::optional<T>. Here's an example for a made-up type MyType:
struct MyType {
// ...
}
std::optional<MyType> calculateOptional() {
// ... lengthy calculation
if (success) {
return MyType(/* etc */);
}
return std::nullopt;
}
Let's assume these functions are costly to run and I want to avoid calling them more than once.
When calling them I want to immediately test the optional, and if it does contain a value, I want to use it immediately and never again. In Swift, for example, I can use the standard if-let statement:
if let result = calculateOptional() {
// Use result var
}
I would like to replicate this test-and-unwrap behavior in C++, while keeping the code as clean as possible at the point of use. For example, the obvious simple solution (to me at least) would be:
if (auto result = calculateOptional()) {
MyType result_unwrapped = *result;
// Use result_unwrapped var
}
But you have to unwrap inside the if, or use *result everywhere, which you don't have to do with Swift.
My only solution so far that genuinely gets close to the look and feel of Swift is:
template<typename T> bool optionalTestUnwrap(std::optional<T> opt, T& value) {
if (!opt.has_value()) { return false; }
value = *opt;
return true;
}
#define ifopt(var, opt) if (typename decltype((opt))::value_type (var); optionalTestUnwrap((opt), (var)))
ifopt (result, calculateOptional()) {
// Use result var
}
...but I'm also not a big fan of the use of a macro to replace a normal if statement.
Personally, I would just do:
if (auto result = calculateOptional()) {
// use *result
}
with a second best of giving the optional an ugly name and making a nicer-named alias for it:
if (auto resultOpt = calculateOptional()) {
auto& result = *resultOpt;
// use result
}
I think this is good enough. It's a great use-case for intentionally shadowing an outer-scope name (i.e. naming both the optional and the inner alias result), but I don't think we need to go crazy here. Even using *result isn't a big problem - the type system will likely catch all misuses.
If we really want to go in on Swift, the macro you're using requires default construction - and it's not really necessary. We can do a little bit better with (ideally __opt is replaced by a mechanism that selects a unique name, e.g. concatenating with __LINE__):
#define if_let(name, expr) \
if (auto __opt = expr) \
if (auto& name = *__opt; false) {} else
As in:
if_let(result, calculateOptional()) {
// use result
} else {
// we didn't get a result
}
This doesn't have any extra overhead or requirements. But it's kind of ridiculous, has its own problems, and doesn't seem worthwhile. But if we're just having fun, this works.
Another simple and potentially safer one:
#define unwrap(x, val, block) if (auto opt_##x = val) { auto &x = opt_##x; block }
Usage:
unwrap(result, calculateOptional(), {
// use result
});
You could wrap the optional in an own type with implicit conversion to the type and explicit to bool. Sorry I haven't tested this so far but I think it should work.
template<class T>
struct opt {
std::optional<T> _optional; // public so it stays an aggregate, probably writing constructors is better
explicit bool() const {
return _optional.has_value();
}
T&() {
return *_optional;
}
const T&() const {
return *_optional;
}
T&&() && { // Let's be fancy
return std::move(*optional);
}
}
opt<int> blub(bool val) {
return val ? opt<int>{0} : opt<int>{std::nullopt};
}
int main() {
if(auto x = blub(val)) { // I hope this works as I think it does
int y = x+1;
}
}
If calculateOptional() returns a std::pair<bool sucess, T result> or can be converted in one, you can use the following construct:
if (auto [s, result] = calculatePair(); s) {
} else {
}
or you use exceptions; (...) catches all exceptions
try {
auto result = calculate();
} catch (...) {
}
but you can be more specific
try {
auto result = calculate();
} catch (nosuccess) {
}
This could be a clean way, inspired by all other answers in this post:
template <typename T>
inline std::pair<bool, T> _unwrap(const std::optional<T> &val) {
return { val.has_value(), *val };
}
#define unwrap(x, val) const auto &[_##x, x] = _unwrap(val); (_##x)
Usage:
if (unwrap(result, calculateOptional())) {
// result is now equivalent to *calculateOptional()
}
Pros:
You don't mess with the if statement
It maintains a method-like feel to it
You can still add more conditions to the right of the if statement
Cons:
Read-only but then again optionals already are
Happy to hear of any issues/fixes you guys might think there might be with this solution.

How can I construct an instance of an immutable data type using branching logic?

I am programming in C++ and trying to use immutable data types, as a way to learn something new, and also because I have been told that using immutable data types can make it easier to reason about the effects of code, because you know that once an instance is constructed it cannot be changed.
Often I want to create an instance of data using branching logic. For example:
int x = 0;
if (a)
{
x = 1;
}
else
{
if (b)
{
x = 2;
}
else
{
x = 3;
}
}
DoSomething(x);
However, if my data type is immutable, that code will not compile, because there cannot be a copy assignment operator:
struct Immutable
{
public:
const int x;
Immutable(const int x)
: x(x)
{}
}
Immutable x(0);
if (a)
{
x = Immutable(1); // Compiler error
...
I can think of 2 possible solutions. First, I could use the ternary operator to construct my data based on a condition:
Immutable x = a ? Immutable(1) : (b ? Immutable(2) : Immutable(3));
But this leads to complicated syntax very quickly.
Alternatively, I could use a std::unique_ptr:
std::unique_ptr<Immutable> x = nullptr;
if (a)
{
x = std::unique_ptr<Immutable>(new Immutable(1));
}
else
{
if (b)
{
x = std::unique_ptr<Immutable>(new Immutable(2));
}
else
{
x = std::unique_ptr<Immutable>(new Immutable(3));
}
}
DoSomething(*x);
But this seems to me like it might be negating the benefit of using immutable data in the first place.
Finally, it may be the case that what I am trying to do makes no sense, and I should just use mutable data types.
What is the proper technique to use to reap the benefits of immutability?
Just create your arguments as independent variables. In the case you presented:
int n;
if (whatever) {
n = 0;
} else {
n = 1;
}
Immutable x(n);
If you need to initialize it in one line (for example, in the initialization list of a constructor), then simply put your logic in a function.
Immutable foo() {
int n;
if (whatever) {
n = 0;
} else {
n = 1;
}
return Immutable(n);
}
struct Thingy {
Immutable x;
Thingy() :x(foo()) {}
};
unique_ptr is almost appropriate, except it does a heap allocation. We can make our own smart pointercontainer class though.
#include <memory>
#include <utility>
template<class T> struct onstack {
__attribute__((__aligned__(__alignof__(T))))
char buffer[sizeof(T)];
bool initialized;
onstack() : initialized(false) {}
~onstack() { if (initialized) (*this)->~T(); initialized = false; }
template<class... Args> void operator()(Args&&... args) {
if (initialized) (*this)->~T();
initialized = false;
new (buffer) T(std::forward<Args>(args)...);
initialized = true;
}
operator boolean() { return initialized; }
T& operator*() { return reinterpret_cast<T&>(buffer); }
T* operator->() { return initialized ? &**this : nullptr; }
};
onstack<Immutable> x;
if (a)
x(1);
else if (b)
x(2);
else
x(3);
This might be useful if the different branches took different arguments.

Abstract Factory Improvements

Edited: I decided to edit this post for future readers. Put simply, it shows an acceptable way to call constructors of template types within the template list. For example, the following:
int main()
{
unique_ptr<factory> real_widget_factory(new widget_factory(5.0, 6.0));
}
Instead of just being limited to:
unique_ptr<factory> real_widget_factory(new widget_factory()); // empty
The Standard provides all the necessary infrastructure you need. You can delete all of that code.
template<typename T, typename... Args> std::unique_ptr<T> make_unique(Args&&... args) {
return std::unique_ptr<T>(std::forward<Args>(args)...);
}
struct train_factory {
train_factory(std::function<std::unique_ptr<locomotive>()> ml,
std::function<std::unique_ptr<freight_car>()> mc)
: make_locomotive(std::move(ml)),
, make_car(std::move(mc)) {}
std::function<std::unique_ptr<locomotive>()> make_locomotive;
std::function<std::unique_ptr<freight_car>()> make_car;
};
train_factory make_concrete_factory(double x1, double x2) {
return train_factory(
[=] { return make_unique<real_locomotive>(x1); },
[=] { return make_unique<real_car>(x2); }
);
}
int main() {
auto fact = make_concrete_factory(1.0);
auto loc = fact.make_locomotive();
}
This appears to meet all of your requirements. In this case, the functions have the arguments to the factory bound in (and this binding is arbitrary). You can of course also modify the functions to take the arguments if you like, or use both in arbitrary ways and combinations.
struct train_factory {
std::function<std::unique_ptr<locomotive>(double)> make_locomotive;
std::function<std::unique_ptr<freight_car>(double)> make_car;
};
train_factory make_concrete_factory() {
return train_factory {
[](double x1) { return make_unique<real_locomotive>(x1); },
[](double x2) { return make_unique<real_car>(x2); }
};
}
int main() {
auto fact = make_concrete_factory();
auto loc = fact.make_locomotive(1.0);
}

Using Lambda/Template/SFINAE to automate try/catch-safeguarding of trampoline functions

I have 100 or so trampoline functions. I would like to know whether it is possible to automate wrapping each one inside a try/catch block.
Please be warned in advance, this is not an easy question. I will start by describing the problem with (simplified) code, and will then attempt to answer it as best I can below, so the reader may see where I am at.
Foo has a function pointer table:
EDIT: This is a C function pointer table. So it could accept static W::w.
Signatures are here: http://svn.python.org/projects/python/trunk/Include/object.h
EDIT: I've attempted a test case here:
class Foo {
Table table;
Foo() {
// Each slot has a default lambda.
:
table->fp_53 = [](S s, A a, B b) -> int {cout<<"load me!";};
table->fp_54 = [](S s, C c, D d, E e) -> float {cout<<"load me!";};
// ^ Note: slots MAY have different signatures
// only the first parameter 'S s' is guaranteed
}
// Foo also has a method for loading a particular slot:
:
void load53() { table->fp_53 = func53; }
void load54() { table->fp_54 = func54; }
:
}
If a particular slot is 'loaded', this is what gets loaded into it:
int func53(S s, A a, B b) {
try{
return get_base(s)->f53(a,b);
}
catch(...) { return 42;}
}
float func54(S s, C c, D d, E e) {
try{
return get_base(s)->f54(c,d,e);
}
catch(...) { return 3.14;}
}
I am trying to accomplish this using lambdas, so as to bypass having to define all of these func53 separately. Something like this:
class Foo {
:
void load53() {
table->fp_53 =
[](S s, A a, B b)->int { return get_base(s)->f53(a,b); }
}
void load54() {
table->fp_54 =
[](S s, C c, D d, E e)->float { return get_base(s)->f54(c,d,e); }
}
However, this is failing to trap errors. I need to be putting a try/catch around the return statement:
try{ return get_base(s)->f53(a,b); } catch{ return 42; }
However, this creates a lot of clutter. It would be nice if I could do:
return trap( get_base(s)->f53(a,b); )
My question is: is there any way to write this trap function (without using #define)?
This is what I've come up with so far:
I think this would pass all the necessary information:
trap<int, &Base::f53>(s,a,b)
trap's definition could then look like this:
template<typename RET, Base::Func>
static RET
trap(S s, ...) {
try {
return get_base(s)->Func(...);
}
catch {
return std::is_integral<RET>::value ? (RET)(42) : (RET)(3.14);
}
}
This may allow for a very clean syntax:
class Foo {
:
void load53() { table->fp_53 = &trap<int, &Base::f53>; }
void load54() { table->fp_54 = &trap<float, &Base::f54>; }
}
At this point I'm not even sure whether some laws have been violated. table->fp_53 must be a valid C function pointer.
Passing in the address of a nonstatic member function (&Base::f53>) won't violate this, as it is a template parameter, and is not affecting the signature for trap
Similarly, ... should be okay as C allows varargs.
So if this is indeed valid, can it be cleaned up?
My thoughts are:
1) maybe the ... should be moved back to the template parameter as a pack.
2) maybe it is possible to deduce the return type for trap, and save one template parameter
3) that Base::Func template parameter is illegal syntax. And I suspect it isn't even close to something legal. Which might scupper the whole approach.
#include <utility>
template <typename T, T t>
struct trap;
template <typename R, typename... Args, R(Base::*t)(Args...)>
struct trap<R(Base::*)(Args...), t>
{
static R call(int s, Args... args)
{
try
{
return (get_base(s)->*t)(std::forward<Args>(args)...);
}
catch (...)
{
return std::is_integral<R>::value ? static_cast<R>(42)
: static_cast<R>(3.14);
}
}
};
Usage:
table->fp_53 = &trap<decltype(&Base::f53), &Base::f53>::call;
table->fp_54 = &trap<decltype(&Base::f54), &Base::f54>::call;
DEMO
Note: std::forward can still be used although Args is not a forwarding reference itself.
template<typename RET, typename... Args>
struct trap_base {
template<RET (Base::* mfptr)(Args...)>
static RET
trap(S s, Args... args) {
try {
return (get_base(s).*mfptr)(args...);
}
catch (...) {
return std::is_integral<RET>::value ? (RET)(42) : (RET)(3.14);
}
}
};
Usage:
void load53() { table.fp_53 = &trap_base<int, int>::trap<&Base::f53>; }
void load54() { table.fp_54 = &trap_base<float, int, float>::trap<&Base::f54>; }
Demo.
You can probably also use a partial specialization to extract RET and Args from decltype(&base::f53) etc.
trap_gen is a function that returns a function pointer to a function generated on the fly, the equivalent of your trap function.
Here is how you use it
table->fp_53 = trap_gen<>(Base::f53);
table->fp_54 = trap_gen<>(Base::f54);
...
Where Base::f53 and Base::f54 are static member functions (or function pointers, or global functions in a namespace).
Proof of concept :
#include <iostream>
template<typename R, class...A>
R (*trap_gen(R(*f)(A...)))(A...)
{
static auto g = f;
return [](A... a)
{
try {
return g(a...);
} catch (...) {
return std::is_integral<R>::value ? static_cast<R>(42)
: static_cast<R>(3.14);
}
};
}
int add(int a, int b)
{
return a+b;
}
int main() {
int(*f)(int, int) = trap_gen<>(add);
std::cout << f(2, 3) << std::endl;
return 0;
}

Does C++ have "with" keyword like Pascal?

with keyword in Pascal can be use to quick access the field of a record.
Anybody knows if C++ has anything similar to that?
Ex:
I have a pointer with many fields and i don't want to type like this:
if (pointer->field1) && (pointer->field2) && ... (pointer->fieldn)
what I really want is something like this in C++:
with (pointer)
{
if (field1) && (field2) && .......(fieldn)
}
Probably the closest you can get is this: (this is just an academic exercise. Of course, you can't use any local variables in the body of these artificial with blocks!)
struct Bar {
int field;
};
void foo( Bar &b ) {
struct withbar : Bar { void operator()() {
cerr << field << endl;
}}; static_cast<withbar&>(b)();
}
Or, a bit more demonically,
#define WITH(T) do { struct WITH : T { void operator()() {
#define ENDWITH(X) }}; static_cast<WITH&>((X))(); } while(0)
struct Bar {
int field;
};
void foo( Bar &b ) {
if ( 1+1 == 2 )
WITH( Bar )
cerr << field << endl;
ENDWITH( b );
}
or in C++0x
#define WITH(X) do { auto P = &X; \
struct WITH : typename decay< decltype(X) >::type { void operator()() {
#define ENDWITH }}; static_cast<WITH&>((*P))(); } while(0)
WITH( b )
cerr << field << endl;
ENDWITH;
no there is no such keyword.
I like to use:
#define BEGIN_WITH(x) { \
auto &_ = x;
#define END_WITH() }
Example:
BEGIN_WITH(MyStructABC)
_.a = 1;
_.b = 2;
_.c = 3;
END_WITH()
In C++, you can put code in a method of the class being reference by pointer. There you can directly reference the members without using the pointer. Make it inline and you pretty much get what you want.
Even though I program mostly in Delphi which has a with keyword (since Delphi is a Pascal derivative), I don't use with. As others have said: it saves a bit on typing, but reading is made harder.
In a case like the code below it might be tempting to use with:
cxGrid.DBTableView.ViewData.Records.FieldByName('foo').Value = 1;
cxGrid.DBTableView.ViewData.Records.FieldByName('bar').Value = 2;
cxGrid.DBTableView.ViewData.Records.FieldByName('baz').Value = 3;
Using with this looks like this
with cxGrid.DBTableView.ViewData.Records do
begin
FieldByName('foo').Value = 1;
FieldByName('bar').Value = 2;
FieldByName('baz').Value = 3;
end;
I prefer to use a different technique by introducing an extra variable pointing to the same thing with would be pointing to. Like this:
var lRecords: TDataSet;
lRecords := cxGrid.DBTableView.ViewData.Records;
lRecords.FieldByName('foo').Value = 1;
lRecords.FieldByName('bar').Value = 2;
lRecords.FieldByName('baz').Value = 3;
This way there is no ambiguity, you save a bit on typing and the intent of the code is clearer than using with
No, C++ does not have any such keyword.
The closest you can get is method chaining:
myObj->setX(x)
->setY(y)
->setZ(z)
for setting multiple fields and using for namespaces.
C++ does not have a feature like that. And many consider "WITH" in Pascal to be a problem because it can make the code ambiguous and hard to read, for example it hard to know if field1 is a member of pointer or a local variable or something else. Pascal also allows multiple with-variables such as "With Var1,Var2" which makes it even harder.
with (OBJECT) {CODE}
There is no such thing in C++.
You can put CODE as is into a method of OBJECT, but it is not always desirable.
With C++11 you can get quite close by creating alias with short name for OBJECT.
For example code given in question it will look like so:
{
auto &_ = *pointer;
if (_.field1 && ... && _.fieldn) {...}
}
(The surrounding curly braces are used to limit visibility of alias _ )
If you use some field very often you can alias it directly:
auto &field = pointer->field;
// Even shorter alias:
auto &_ = pointer->busy_field;
No, there is no with keyword in C/C++.
But you can add it with some preprocessor code:
/* Copyright (C) 2018 Piotr Henryk Dabrowski, Creative Commons CC-BY 3.0 */
#define __M2(zero, a1, a2, macro, ...) macro
#define __with2(object, as) \
for (typeof(object) &as = (object), *__i = 0; __i < (void*)1; ++__i)
#define __with1(object) __with2(object, it)
#define with(...) \
__M2(0, ##__VA_ARGS__, __with2(__VA_ARGS__), __with1(__VA_ARGS__))
Usage:
with (someVeryLongObjectNameOrGetterResultOrWhatever) {
if (it)
it->...
...
}
with (someVeryLongObjectNameOrGetterResultOrWhatever, myObject) {
if (myObject)
myObject->...
...
}
Simplified unoverloaded definitions (choose one):
unnamed (Kotlin style it):
#define with(object) \
for (typeof(object) &it = (object), *__i = 0; __i < (void*)1; ++__i)
named:
#define with(object, as) \
for (typeof(object) &as = (object), *__i = 0; __i < (void*)1; ++__i)
Of course the for loop always has only a single pass and will be optimized out by the compiler.
First I've heard that anybody doesn't like 'with'. The rules are perfectly straightforward, no different from what happens inside a class in C++ or Java. And don't overlook that it can trigger a significant compiler optimization.
The following approach relies on Boost. If your compiler supports C++0x's auto then you can use that and get rid of the Boost dependence.
Disclaimer: please don't do this in any code that must be maintained or read by someone else (or even by yourself in a few months):
#define WITH(src_var) \
if(int cnt_ = 1) \
for(BOOST_AUTO(const & _, src_var); cnt_; --cnt_)
int main()
{
std::string str = "foo";
// Multiple statement block
WITH(str)
{
int i = _.length();
std::cout << i << "\n";
}
// Single statement block
WITH(str)
std::cout << _ << "\n";
// Nesting
WITH(str)
{
std::string another("bar");
WITH(another)
assert(_ == "bar");
}
}
Having written numerous parsers, this seems like a dead simple list look up for the named object, either static or dynamic. Further, I have never seen a situation where the compiler did not correctly identify the missing object and type, so all those lame excuses for not allowing a WITH ...ENDWITH construction would seem to be a lot of hooey. For the rest of us prone to long object names one workaround is to create simple defines. Couldn't resist, suppose I have:
#include<something>
typedef int headache;
class grits{
public:
void corn(void);
void cattle(void);
void hay(void);}; //insert function defs here
void grits::grits(void)(printf("Welcome to Farm-o-mania 2012\n");};
#define m mylittlepiggy_from_under_the_backporch.
headache main(){
grits mylittlepiggy_from_under_the_backporch;
m corn(); //works in GCC
m cattle();
m hay();
return headache;
#include <iostream>
using namespace std;
template <typename T>
struct with_iter {
with_iter( T &val ) : p(&val) {}
inline T* begin() { return p; }
inline T* end() { return p+1; }
T *p;
};
#define with( N, I ) for( auto &N : with_iter<decltype(I)>(I) )
int main() {
with( out , cout ) {
out << "Hello world!" << endl;
}
return 0;
}
Nuf said ...
I can see one instance where 'with' is actually useful.
In methods for recursive data structures, you often have the case:
void A::method()
{
for (A* node = this; node; node = node->next) {
abc(node->value1);
def(value2); // -- oops should have been node->value2
xyz(node->value3);
}
}
errors caused by typos like this are very hard to find.
With 'with' you could write
void A::method()
{
for (A* node = this; node; node = node->next) with (node) {
abc(value1);
def(value2);
xyz(value3);
}
}
This probably doesn't outweight all the other negatives mentioned for 'with', but just as an interesting info...
Maybe you can:
auto p = *pointer;
if (p.field1) && (p.field2) && ... (p.fieldn)
Or create a small program that will understand with statements in C++ and translate them to some form of a valid C++.
I too came from the Pascal world..... .....and I also LOVE Python's use of with (basically having an automatic try/finally):
with open(filename, "r") as file:
for line in file:
if line.startswith("something"):
do_more()
That acts like a smart ptr object. It does not go into the block if the open failed; and when leaving the block, the file if closed.
Here is a sample very close to Pascal while also supporting Python's usage (assuming you have a smart object with destructor cleanup); You need newer C++ standard compilers for it to work.
// Old way
cxGrid_s cxGrid{};
cxGrid.DBTableView.ViewData.Records.FieldByName.value["foo"] = 1;
cxGrid.DBTableView.ViewData.Records.FieldByName.value["bar"] = 2;
cxGrid.DBTableView.ViewData.Records.FieldByName.value["baz"] = 3;
// New Way - FieldByName will now be directly accessible.
// the `;true` is only needed if the call does not return bool or pointer type
if (auto FieldByName = cxGrid.DBTableView.ViewData.Records.FieldByName; true)
{
FieldByName.fn1 = 0;
FieldByName.fn2 = 3;
FieldByName.value["foo"] = 1;
FieldByName.value["bar"] = 2;
FieldByName.value["baz"] = 3;
}
And if you want even closer:
#define with if
with (auto FieldByName = cxGrid.DBTableView.ViewData.Records.FieldByName; true)
// Similar to the Python example
with (smartFile sf("c:\\file.txt"); sf)
{
fwrite("...", 1, 3, *sf);
}
// Usage with a smart pointer
with (std::unique_ptr<class_name> p = std::make_unique<class_name>())
{
p->DoSomethingAmazing();
// p will be released and cleaned up upon exiting the scope
}
The (quick and dirty) supporting code for this example:
#include <map>
#include <string>
struct cxGrid_s {
int g1, g2;
struct DBTableView_s {
int tv1, tv2;
struct ViewData_s {
int vd1, vd2;
struct Records_s {
int r1, r2;
struct FieldByName_s{
int fn1, fn2;
std::map<std::string, int> value;
} FieldByName;
} Records;
} ViewData;
} DBTableView;
};
class smartFile
{
public:
FILE* f{nullptr};
smartFile() = delete;
smartFile(std::string fn) { f = fopen(fn.c_str(), "w"); }
~smartFile() { if (f) fclose(f); f = nullptr; }
FILE* operator*() { return f; }
FILE& operator->() { return *f; }
operator bool() const { return f != nullptr; }
};
I was lamenting to PotatoSwatter (currently accepted answer) that I could not access variables declared in the enclosing scope with that solution.
I tried to post this in a comment response to PotatoSwatter, but it's better as a whole post. It's all a bit over the top, but the syntax sugar is pretty nice!
#define WITH_SIG float x, float y, float z
#define WITH_ARG x, y, z
#define WITH(T,s) do { struct WITH : T { void operator()(s) {
#define ENDWITH(X,s) }}; static_cast<WITH&>((X))(s); } while(0)
class MyClass {
Vector memberVector;
static void myFunction(MyClass* self, WITH_SIG) {
WITH(MyClass, WITH_SIG)
memberVector = Vector(x,y,z);
ENDWITH(*self, WITH_ARG);
}
}
A simple way to do this is as follows
class MyClass
{
int& m_x;
public MyClass(int& x)
{
m_x = x;
m_x++;
}
~MyClass()
{
m_x--;
}
}
int main():
{
x = 0;
{
MyClass(x) // x == 1 whilst in this scope
}
}
I've been writing python all day long and just scrapped this down before anyone takes me to the cleaners. In a larger program this is an example of how to keep a reliable count for something.