I wish to serialise a std::optional<float> with nlohmann-json.
The example given here in the docs for a boost::optional seems very close to what I want, but I don't understand where my adaptation of it is going wrong.
It seems that the deserialization component is working for me, but not the to_json aspect.
Here is a minimal working example
// OptionalSeriealisationTest.cpp
//#define JSON_USE_IMPLICIT_CONVERSIONS 0
// Tried toggling this as per this comment
// https://github.com/nlohmann/json/issues/1749#issuecomment-772996219 with no effect
// (no effect noticed)
#include <iostream>
#include <optional>
#include <nlohmann/json.hpp>
namespace nlohmann
{
template <typename T>
struct adl_serializer<std::optional<T>>
{
// This one is the issue
static void to_json(json& j, const std::optional<T>& opt) {
//if (opt == std::nullopt) {
// j = nullptr;
//}
//else {
// j = *opt; // this will call adl_serializer<t>::to_json which will
// // find the free function to_json in t's namespace!
//}
if (opt)
{
j = opt.value();
}
else
{
j = nullptr;
}
//NB same errors on the block above and the commented-out version
}
static void from_json(const json& j, std::optional<T>& opt) {
if (j.is_null()) {
opt = std::nullopt;
}
else {
opt = j.get<T>(); // same as above, but with
// adl_serializer<t>::from_json
}
}
};
}
using json = nlohmann::ordered_json;
int main()
{
{
// Seems ok, breakpoints on the from_json are hit
json j;
j["x"] = 4.0f;
std::optional<float> x;
j.at("x").get_to<std::optional<float>>(x);
std::cout << x.has_value() << std::endl;
std::cout << x.value() << std::endl;
}
{
// Seems ok, breakpoints on the from_json are hit
json j;
j["x"] = nullptr;
std::optional<float> x = 4.0f;
j.at("x").get_to<std::optional<float>>(x);
std::cout << x.has_value() << std::endl;
//std::cout << x.value() << std::endl;
}
{
// Won't compile on MSVC
std::optional<float> x = 4.0;
json j;
j["x"] = x;
}
{
// Won't compile on MSVC
std::optional<float> x = 4.0;
auto j = json({ "x", x });
}
}
The the to_json aspects will not compile in MSVC with the following error
Severity Code Description Project File Line Suppression State
Error (active) E0289
no instance of constructor
"nlohmann::basic_json<ObjectType, ArrayType, StringType,
BooleanType, NumberIntegerType, NumberUnsignedType, NumberFloatType,
AllocatorType, JSONSerializer, BinaryType>::basic_json
[with ObjectType=nlohmann::ordered_map, ArrayType=std::vector,
StringType=std::string, BooleanType=bool, NumberIntegerType=int64_t,
NumberUnsignedType=uint64_t, NumberFloatType=double,
AllocatorType=std::allocator, JSONSerializer=nlohmann::adl_serializer,
BinaryType=std::vector<uint8_t, std::allocator<uint8_t>>]"
matches the argument list
My specific asks are
What's the fix?
Why does this go wrong, when it seems so close to their example (boost::optional vs std::optional?)
I note there are some quite lengthy discussions on the project about trouble incorporating std::optionals into the lib itself although I don't fully follow it and understand what it means for me in practice wanting to use std::optional as a third-party object. Some of the comments suggest approaches similar to what I have here work, so I hope it amounts to an oversight / silly mistake.
Cheers!
This amounted to a dumb-one that's hard to spot because you're too worried its something esoteric. It's probabally quite specific to my mistake and wont likely be too much use to anyone finding this in the future though.
Nonetheless, answer is as follows.
My MWE about is a simplification of something in a real codebase. The codebase uses orderd_json specifically, but short hands it to json, i.e.
using json = nlohmann::ordered_json;
The class using the word json in nlohmann is a different, more general class. It looks like when serialising to an ordered_json it needs to be specifically for the type ordered_json and can't be automagically coaxed in.
I.e. I should ha to_json taking type ordered_json as it's first argument.
static void to_json(ordered_json& j, const std::optional<T>& opt) {/*...*/}
rather than
static void to_json(json& j, const std::optional<T>& opt) {/*...*/}
It just turned out from_json worked anyway.
Related
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.
Our Python codebase has metrics-related code that looks like this:
class Timer:
def __enter__(self, name):
self.name = name
self.start = time.time()
def __exit__(self):
elapsed = time.time() - self.start
log.info('%s took %f seconds' % (self.name, elapsed))
...
with Timer('foo'):
do some work
with Timer('bar') as named_timer:
do some work
named_timer.some_mutative_method()
do some more work
In Python's terminology, the timer is a contextmanager.
Now we want to implement the same thing in C++, with an equally nice syntax. Unfortunately, C++ doesn't have with. So the "obvious" idiom would be (classical RAII)
class Timer {
Timer(std::string name) : name_(std::move(name)) {}
~Timer() { /* ... */ }
};
if (true) {
Timer t("foo");
do some work
}
if (true) {
Timer named_timer("bar");
do some work
named_timer.some_mutative_method();
do some more work
}
But this is extremely ugly syntactic salt: it's many lines longer than it needs to be, we had to introduce a name t for our "unnamed" timer (and the code breaks silently if we forget that name)... it's just ugly.
What are some syntactic idioms that people have used to deal with "contextmanagers" in C++?
I've thought of this abusive idea, which reduces the line-count but doesn't get rid of the name t:
// give Timer an implicit always-true conversion to bool
if (auto t = Timer("foo")) {
do some work
}
Or this architectural monstrosity, which I don't even trust myself to use correctly:
Timer("foo", [&](auto&) {
do some work
});
Timer("bar", [&](auto& named_timer) {
do some work
named_timer.some_mutative_method();
do some more work
});
where the constructor of Timer actually invokes the given lambda (with argument *this) and does the logging all in one go.
Neither of those ideas seems like a "best practice", though. Help me out here!
Another way to phrase the question might be: If you were designing std::lock_guard from scratch, how would you do it so as to eliminate as much boilerplate as possible? lock_guard is a perfect example of a contextmanager: it's a utility, it's intrinsically RAII, and you hardly ever want to bother naming it.
It's possible to mimic the Python syntax and semantics quite closely. The following test case compiles and has largely similar semantics to what you'd have in Python:
// https://github.com/KubaO/stackoverflown/tree/master/questions/pythonic-with-33088614
#include <cassert>
#include <cstdio>
#include <exception>
#include <iostream>
#include <optional>
#include <string>
#include <type_traits>
[...]
int main() {
// with Resource("foo"):
// print("* Doing work!\n")
with<Resource>("foo") >= [&] {
std::cout << "1. Doing work\n";
};
// with Resource("foo", True) as r:
// r.say("* Doing work too")
with<Resource>("bar", true) >= [&](auto &r) {
r.say("2. Doing work too");
};
for (bool succeed : {true, false}) {
// Shorthand for:
// try:
// with Resource("bar", succeed) as r:
// r.say("Hello")
// print("* Doing work\n")
// except:
// print("* Can't do work\n")
with<Resource>("bar", succeed) >= [&](auto &r) {
r.say("Hello");
std::cout << "3. Doing work\n";
} >= else_ >= [&] {
std::cout << "4. Can't do work\n";
};
}
}
That's given
class Resource {
const std::string str;
public:
const bool successful;
Resource(const Resource &) = delete;
Resource(Resource &&) = delete;
Resource(const std::string &str, bool succeed = true)
: str(str), successful(succeed) {}
void say(const std::string &s) {
std::cout << "Resource(" << str << ") says: " << s << "\n";
}
};
The with free function passes all the work to the with_impl class:
template <typename T, typename... Ts>
with_impl<T> with(Ts &&... args) {
return with_impl<T>(std::forward<Ts>(args)...);
}
How do we get there? First, we need a context_manager class: the traits class that implements the enter and exit methods - the equivalents of Python's __enter__ and __exit__. As soon as the is_detected type trait gets rolled into C++, this class can also easily forward to the compatible enter and exit methods of the class type T, thus mimicking Python's semantics even better. As it stands, the context manager is rather simple:
template <typename T>
class context_manager_base {
protected:
std::optional<T> context;
public:
T &get() { return context.value(); }
template <typename... Ts>
std::enable_if_t<std::is_constructible_v<T, Ts...>, bool> enter(Ts &&... args) {
context.emplace(std::forward<Ts>(args)...);
return true;
}
bool exit(std::exception_ptr) {
context.reset();
return true;
}
};
template <typename T>
class context_manager : public context_manager_base<T> {};
Let's see how this class would be specialized to wrap the Resource objects, or std::FILE *.
template <>
class context_manager<Resource> : public context_manager_base<Resource> {
public:
template <typename... Ts>
bool enter(Ts &&... args) {
context.emplace(std::forward<Ts>(args)...);
return context.value().successful;
}
};
template <>
class context_manager<std::FILE *> {
std::FILE *file;
public:
std::FILE *get() { return file; }
bool enter(const char *filename, const char *mode) {
file = std::fopen(filename, mode);
return file;
}
bool leave(std::exception_ptr) { return !file || (fclose(file) == 0); }
~context_manager() { leave({}); }
};
The implementation of the core functionality is in the with_impl type. Note how the exception handling within the suite (the first lambda) and the exit function mimic Python behavior.
static class else_t *else_;
class pass_exceptions_t {};
template <typename T>
class with_impl {
context_manager<T> mgr;
bool ok;
enum class Stage { WITH, ELSE, DONE } stage = Stage::WITH;
std::exception_ptr exception = {};
public:
with_impl(const with_impl &) = delete;
with_impl(with_impl &&) = delete;
template <typename... Ts>
explicit with_impl(Ts &&... args) {
try {
ok = mgr.enter(std::forward<Ts>(args)...);
} catch (...) {
ok = false;
}
}
template <typename... Ts>
explicit with_impl(pass_exceptions_t, Ts &&... args) {
ok = mgr.enter(std::forward<Ts>(args)...);
}
~with_impl() {
if (!mgr.exit(exception) && exception) std::rethrow_exception(exception);
}
with_impl &operator>=(else_t *) {
assert(stage == Stage::ELSE);
return *this;
}
template <typename Fn>
std::enable_if_t<std::is_invocable_r_v<void, Fn, decltype(mgr.get())>, with_impl &>
operator>=(Fn &&fn) {
assert(stage == Stage::WITH);
if (ok) try {
std::forward<Fn>(fn)(mgr.get());
} catch (...) {
exception = std::current_exception();
}
stage = Stage::ELSE;
return *this;
}
template <typename Fn>
std::enable_if_t<std::is_invocable_r_v<bool, Fn, decltype(mgr.get())>, with_impl &>
operator>=(Fn &&fn) {
assert(stage == Stage::WITH);
if (ok) try {
ok = std::forward<Fn>(fn)(mgr.get());
} catch (...) {
exception = std::current_exception();
}
stage = Stage::ELSE;
return *this;
}
template <typename Fn>
std::enable_if_t<std::is_invocable_r_v<void, Fn>, with_impl &> operator>=(Fn &&fn) {
assert(stage != Stage::DONE);
if (stage == Stage::WITH) {
if (ok) try {
std::forward<Fn>(fn)();
} catch (...) {
exception = std::current_exception();
}
stage = Stage::ELSE;
} else {
assert(stage == Stage::ELSE);
if (!ok) std::forward<Fn>(fn)();
if (!mgr.exit(exception) && exception) std::rethrow_exception(exception);
stage = Stage::DONE;
}
return *this;
}
template <typename Fn>
std::enable_if_t<std::is_invocable_r_v<bool, Fn>, with_impl &> operator>=(Fn &&fn) {
assert(stage != Stage::DONE);
if (stage == Stage::WITH) {
if (ok) try {
ok = std::forward<Fn>(fn)();
} catch (...) {
exception = std::current_exception();
}
stage = Stage::ELSE;
} else {
assert(stage == Stage::ELSE);
if (!ok) std::forward<Fn>(fn)();
if (!mgr.exit(exception) && exception) std::rethrow_exception(exception);
stage = Stage::DONE;
}
return *this;
}
};
Edit: After reading Dai's comment more carefully, and thinking a bit more, I realized this is a poor choice for C++ RAII. Why? Because you are logging in the destructor, this means you are doing io, and io can throw. C++ destructors should not emit exceptions. With python, writing a throwing __exit__ isn't necessarily awesome either, it can cause you to drop your first exception on the floor. But in python, you definitively know whether the code in the context manager has caused an exception or not. If it caused an exception, you can just omit your logging in __exit__ and pass through the exception. I leave my original answer below in case you have a context manager which doesn't risk throwing on exit.
The C++ version is 2 lines longer than the python version, one for each curly brace. If C++ is only two lines longer than python, that's doing well. Context managers are designed for this specific thing, RAII is more general and provides a strict superset of the functionality. If you want to know best practice, you already found it: have an anonymous scope and create the object at the beginning. This is idiomatic. You may find it ugly coming from python, but in the C++ world it's just fine. The same way someone from C++ will find context managers ugly in certain situations. FWIW I use both languages professionally and this doesn't bother me at all.
That said, I'll provide a cleaner approach for anonymous context managers. Your approach with constructing Timer with a lambda and immediately letting it destruct is pretty weird, so you're right to be suspicious. A better approach:
template <class F>
void with_timer(const std::string & name, F && f) {
Timer timer(name);
f();
}
Usage:
with_timer("hello", [&] {
do something;
});
This is equivalent to the anonymous context manager, in the sense that none of Timer's methods can be called other than construction and destruction. Also, it uses the "normal" class, so you can use the class when you need a named context manager, and this function otherwise. You could obviously write with_lock_guard in a very similar way. There it's even better as lock_guard doesn't have any member functions you're missing out on.
All that said, would I use with_lock_guard, or approve code written by a teammate that added in such a utility? No. One or two extra lines of code just doesn't matter; this function doesn't add enough utility to justify it's own existence. YMMV.
You don't need if( true ), C++ has "anonymous scopes" which can be used to restrict a scope's lifetime in much the same was as Python's with or C#s using (well, C# also has anonymous scopes too).
Like so:
doSomething();
{
Time timer("foo");
doSomethingElse();
}
doMoreStuff();
Just use bare curly-brackets.
However, I disagree with your idea of using RAII-semantics to instrument code like this as the timer destructor is non-trivial and has side-effects by-design. It might be ugly and repetitive, but I feel explicitly calling named startTimer, stopTimer and printTimer methods make the program more "correct" and self-documenting. Side-effects are bad, m'key?
I have recently started a C++ project to mimic Python's context manager as I migrate a python code base over to C++, found at https://github.com/batconjurer/contextual.
For this flow, you need to define a resource manager derived from an interface named IResource. Below, this is called Timer. It is in this class that the enter and exit functions are implemented. The context is just the code block that requires the resources, so it is passed via anonymous function.
The resource manager expects you to implement the IData struct which is uses to store the acquired resources. It actually only keeps a pointer to an IData instance.
For your use case, the following is an example implementation that compiles with C++17.
#include "include/contextual.h"
#include <ctime>
#include <chrono>
#include <thread>
using namespace Contextual;
namespace Contextual {
struct IData {
std::string name;
std::time_t start_time = std::time(NULL);
void reset_time() {
std::cout << "Time before restart: " << start_time << "\n";
std::time(&start_time);
std::cout << "Time after restart: " << start_time << "\n";
};
};
class Timer : public IResource<IData> {
private:
IData _data;
void enter() override {
std::time(&resources->start_time);
}
void exit(std::optional<std::exception> e) override {
double elapsed_time = std::time(NULL) - resources->start_time;
std::cout << resources->name << " took " << elapsed_time << " seconds.\n";
if (e) {
throw e.value();
}
}
public:
Timer(std::string &&name) : IResource<IData>(_data), _data(IData{name}){};
};
};
int main(){
With {
Timer(std::string("Foo")) + Context{
[&](IData* time_data) {
std::chrono::milliseconds sleeptime(5000);
std::this_thread::sleep_for(sleeptime); // In place of "Do some work"
time_data->reset_time(); // In place of "some_mutative_function()"
std::this_thread::sleep_for(sleeptime); // In place of "Do some work"
}
}
};
}
There are some nuisances I'm still working on (for example the fact that the IData struct had to be stored as a instance variable of the Timer since only a pointer to it is kept by IResource). And of course C++ exceptions aren't the nicest things.
Inspired by Dai's answer, I ended up with this code:
#include <iostream>
#include <chrono>
class Timer
{
std::chrono::high_resolution_clock::time_point startTime;
public:
Timer(): startTime(std::chrono::high_resolution_clock::now()){};
void elapsed()
{
auto endTime = std::chrono::high_resolution_clock::now();
std::chrono::duration<double, std::milli> elapsedTime = endTime - startTime;
std::cout << elapsedTime.count() << std::endl;
}
};
int main()
{
{
Timer timer=Timer();
std::cout << "This is some work" << std::endl;
timer.elapsed();
}
return 0;
}
I'm much more fluent in python than in c++; I'm not sure if it's idiomatic but it works for me.
I want to do some conditional checks within a bool member function of a struct. How will my struct object struct1 know the bool member function has returned true, so that integers a & b can be used within the calc member function?
int main() {
vector<Point> pt;
pt.push_back(Point{ 1.5, 4.2 });
pt.push_back(Point{ 2.4, 3.1 });
doSth struct1;
bool tempbool = struct1.memfuncbool(pt); //error starts here!
if (tempbool) {int answer = struct1.calc(1);} //??
std::cout << answer;
return 0;
}
struct Point {
double _x;
double _y;
};
struct doSth {
int a, b; //data members
int calc(const int k) {
return (a + b)*k;
}
bool memfuncbool(const vector<Point> &pts) {
//does stuff...
a = var1; //var1 = 1
b = var2; //var2 = 2
return true;
}
}
There are two approaches: encapsulation for caller safety and pure code discipline. In the later you yourself make sure that the code you write is always aware of the latest result of memfuncbool and when and where a and b are set.
In the first you can add a flag in your struct that you set once memfuncbool is called and check in calc (and handle it appropriately.) In that case you should also make sure that the flag is cleared when initialising your struct - either via constructor or again code discipline (like always zero your structs).
An information hiding approach (C++) in the first sense would look like this:
class DoSth {
int a, b;
bool valid;
public:
DoSth() : valid(false) { }
bool isValid() const { return valid; }
/// returns calc if valid, otherwise 0
int calc(int k) const {
return isValid() ? (a + b) * k : 0;
}
void setSth(...) {
a = ...
b = ...
valid = true;
// instead of returning here the caller can check isValid() anytime
}
};
Your code has many issues that could easily be solved if you didn't try to do more than you know.
1 You're defining both Point and doSth structures AFTER the main function. So the main function has no way to know what your structures do. Normally you would use a header file to contain the declaration and the cpp file to contain the implementation, but since you're doing a small program you can just move the definitions of your structures to be above the main function. Alternatively you can declare your structures above main and implement them below, like this.
// Definition of struct Point
struct Point {
double _x;
double _y;
};
// Definition of struct doSth
struct doSth {
int a, b; //data members
// **Declaration** of doSth methods
int calc(const int k);
bool memfuncbool(const std::vector<Point> &pts);
};
int main() {
...
}
// Definition of calc method
int doSth::calc(const int k) {
...
}
// Definition of memfuncbool method
bool doSth::memfuncbool(const std::vector<Point> &pts) {
...
}
2 In the main function you're using a variable called answer in a scope that doesn't know such variable.
if (tempbool) {
int answer = struct1.calc(1);
}
std::cout << answer; // ERROR: answer is not a known variable
See, you're declaring a variable inside an if condition but using it outside. You have to declare the variable outside as well if you want to use it.
int answer = 0;
if ( tempbool ) {
answer = struct1.calc(1);
}
std::cout << answer << std::endl; // OK
OR
if ( tempbool ) {
int answer = strut1.calc(1);
std::cout << answer << std::endl;
}
else {
std::cout << "Invalid result!" << std::endl;
}
This is a fix to compile what you have done so far. But this is not a solution to your code design question.
3 Code Design
Although I suggested quick fixes to your code your actual problem has to do with how you design your classes and structure your code. I've showed you what you did wrong in your code, but your problem can be solved using a better structured approach.
While writing my answer Beyeler already answered this part for you, so check his answer.
EDIT
In your code you are probably doing
using namespace std;
But you've written both vector< Point > and std::cout. You should not use the using line, to begin with, to avoid name collisions and to help YOU know where this vector is coming from.
However, if you insist on using this line so you don't have to write std:: (and it's OK if you know what you're doing), don't go typing std:: on one thing and then omit it in another. Be consistent, either use it or don't.
I found three errors with your code:
"do" is a c++ keyword. You can't use it to name structs.
The parameter of the "memfuncbool" is missing its type. const& is not a type.
Missing semicolon after struct definition.
Also i supposed that var1, var2 and arg are well defined. If they are not even that is a error.
After correcting these errors maybe you can do something like-
if(tempbool) { /*statements*/ };
I have a kindof simple problem I dont know how to solve, its from using python & becoming accustomed with working with variables where the data type doesn't matter . I am working with the windows Task Scheduler & its millions of objects it has, ITask...this ITask...that.
So I have a function, & depending on the parameter triggerType (an enumeration var), the variable trigger will either be of type ITimeTrigger or IBootTrigger ... ugh this is hard to explain in text, if you look at the code below it will be easy to see what my problem is.
Its ALOT easier to understand my issue by looking at my example below:
enum meh { I_WANT_A_INT = 50001, I_WANT_A_FLOAT };
bool foo( meh triggerType )
{
switch ( triggerType )
{
case I_WANT_A_INT:
{
int trigger = 10;
}
break;
case I_WANT_A_FLOAT:
{
float trigger = 10.111;
}
break;
default:
{
double trigger = 11;
}
break;
}
trigger = 5 * trigger ; // Compile error because trigger is not declared
cout << trigger << endl;
}
The solutions I know I can use are:
- I can overload the function & have one for the ITimeTrigger(int) action & another for IBootTrigger(float). This is something I really dont want to do because the function is really long with alot of repeating code between them.
- ITimeTrigger & IBootTrigger both inherit from the same object ITrigger, so I could declare the trigger var outside the switch as ITrigger, then cast to the object I need within the switch. This will work now, but when I
extend this function to schedule a different kind of task trigger will not inherit from ITrigger (win32 semantics again) so this solution wont work.
How can I declare the variable trigger (whose data type will be determined at run time) so I can then work with the var later on in the function?
You can use templates to avoid the code duplication. For example, the above can be rewritten as:
// Common code goes here:
template<typename TriggerType>
void bar(TriggerType trigger)
{
trigger *= 5;
std::cout << trigger << std::endl;
}
// Differing code goes here:
void foo(meh trigger_type)
{
switch (trigger_type) {
case I_WANT_A_INT:
bar(10); // invokes the int version
break;
case I_WANT_A_FLOAT:
bar(10.111f); // invokes the float version; note the use of 'f'
break;
default:
bar(11.0); // invokes the double version; note the use of '.0' and lack of 'f'
}
}
For those types with radically different behavior, you can also have specialized instantiations of bar.
This doesn't really make sense in C++; types are determined at run-time. Whilst you could create a hierarchy of classes that behave similarly to the built-in types, overloading operator*, etc. for them polymorphically, I would question why you want the ability to mix primitive types like this?
If you want different versions of the function for different types, but without code duplication, then you probably want to look at using function templates. See e.g. http://www.parashift.com/c++-faq-lite/templates.html.
#include <iostream>
using namespace std;
enum meh { i_want_a_int = 50001, i_want_a_float };
template< class Number >
bool bar( Number trigger )
{
trigger *= 5;
cout << trigger << endl;
return true;
}
bool foo( meh triggerType )
{
switch ( triggerType )
{
case i_want_a_int:
return bar<int>( 10 );
case i_want_a_float:
return bar<float>( 10.111f );
default:
return bar<double>( 11.0 );
}
}
int main()
{
foo( i_want_a_float );
}
By the way, you can greatly reduce the chance of inadvertent text replacement by reserving ALL_UPPERCASE identifiers for macros.
Cheers & hth,
Templates are the likely solution.
Its had to say without seeing more detail, but I note that you say "the function is really long with a lot of repeating code".
You can have:
a single function template
a refactor into a class template,
with the non type specific code in
base class methods might work well
a collection of function some of
which are templated with the
top-level function being templated
a top level templated function with
overloading of some of the
sub-routines.
Note you also use templating to map from the enum to the type:
enum meh { I_WANT_A_INT = 50001, I_WANT_A_FLOAT, I_WANT_A_DOUBLE };
template<meh = I_WANT_A_DOUBLE>
struct TriggerType
{
typedef double Type;
};
template<>
struct TriggerType<I_WANT_A_INT>
{
typedef int Type;
};
template<>
struct TriggerType<I_WANT_A_FLOAT>
{
typedef float Type;
};
template<class T> void setValue(T& t);
template<> void setValue<double>(double& t) { t = 11;}
template<> void setValue<int>(int& t) { t = 10;}
template<> void setValue<float>(float& t) { t = 10.111f;}
template<class T>
bool fooTyped()
{
T trigger;
setValue(trigger);
trigger *= 5;
std::cout << trigger << std::endl;
return true;
}
bool foo( meh triggerType )
{
bool ret = false;
switch ( triggerType )
{
case I_WANT_A_INT:
{
ret = fooTyped<TriggerType<I_WANT_A_INT>::Type>(); ;
}
break;
case I_WANT_A_FLOAT:
{
ret = fooTyped<TriggerType<I_WANT_A_FLOAT>::Type>(); ;
}
break;
default:
{
ret = fooTyped<TriggerType<I_WANT_A_DOUBLE>::Type>(); ;
}
break;
}
return ret;
}
void test ()
{
foo(I_WANT_A_INT);
foo(I_WANT_A_FLOAT);
foo((meh)63);
}
Note the dispatch on the enum mapping to the type; we need this explicit boiler plate because we can't use a run time value to instantiate the template.
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.