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.
Related
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.
I wanna write a method taking different type of method pointers using argument polymorphism. I thought union will be a good idea in this situation. However, I don't know how to reference to the correct union instance using method argument.
#include <iostream>
union Method {
struct {
void (*a)();
void (*b)(int);
};
};
struct Item {
char c;
Method m;
};
int8_t menu_size = 0;
void add_item(Item menu[], Item item) {
int8_t index = 0;
bool exists = false;
do {
if (menu[index].c == item.c) exists = true;
++index;
} while (menu[index].c == item.c);
//
if (exists) {
menu[index - 1] = item;
} else {
menu[menu_size] = item;
++menu_size;
}
}
void hello();
void ret(int);
int main(void) {
Item menu[2];
add_item(menu, (Item){'h', &hello});
add_item(menu, (Item){'r', &ret});
menu[0].m();
menu[1].m(5);
return 0;
}
void hello() {
std::cout << "Hello, World!\n";
}
void ret(int i) {
std::cout << i << "\n";
}
You are correct, you "don't know how to reference to the correct union instance". That's how unions work. There's nothing about a union that indicates which instance of a union member is the one that's set. Some other, out of band, mechanism must be used to track that, and it is your responsibility to implement it, and manually record or track which union member you set. Some other variable, or flag, somewhere, whose value indicates which union member is set. This is not the only way to do this, of course, but is the simplest one. In any case it's your onus to correctly track of everything, here. It's a lot of work.
Furthermore, C++ inherited unions from C, which does not have classes. And, in C++, unions that contain classes have further restrictions and gotchas, which really bring more hassles than they're worth.
Fortunately, with modern C++, you will always use std::variants instead of union, which solves all of these problems, and does all of the hard work for you to make sure that everything in the union is done correctly, and type-safe.
As an example of std::variant usage:
#include <iostream>
#include <variant>
struct Item {
char c;
std::variant<void (*)(), void (*)(int)> method;
};
int8_t menu_size = 0;
void add_item(Item menu[], Item item) {
int8_t index = 0;
bool exists = false;
do {
if (menu[index].c == item.c) exists = true;
++index;
} while (menu[index].c == item.c);
//
if (exists) {
menu[index - 1] = item;
} else {
menu[menu_size] = item;
++menu_size;
}
}
void hello();
void ret(int);
int main(void) {
Item menu[2];
add_item(menu, (Item){'h', &hello});
add_item(menu, (Item){'r', &ret});
std::get<void(*)()>(menu[0].method)();
std::get<void(*)(int)>(menu[1].method)(5);
return 0;
}
void hello() {
std::cout << "Hello, World!\n";
}
void ret(int i) {
std::cout << i << "\n";
}
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.
I discovered a neat feature years ago while i was searching something on google.
It enabled the usage of a sort of "function" to control access to a member variable but i can't seem to find it anymore. (I am also not sure if this was a c++ feature or only specific to the msvc compiler because it was highlighted red in visual studio as if it was label or something)
The theory behind it was something similar to this:
class A
{
public:
.test(int value)
{
priv = value;
}
private:
int priv = 0;
};
...
A a;
a.test = 14; // Sets priv to 14 ! note no () needed after test´
Does anybody know what it is / was?
Thank you everyone for responding but no, it was not C# like some people desperately tried to tell me.
Microsoft docs - property (C++)
For those interested how it worked:
struct S
{
int i;
void putprop(int j) {
i = j;
}
int getprop() {
return i;
}
__declspec(property(get = getprop, put = putprop)) int the_prop;
};
S s;
s.the_prop = 5;
int test = s.the_prop;
Designated initializer
If I had to speculate, you've most probably seen the C99 designated initializer
It looks like this:
MY_TYPE a = { .flag = true, .value = 123, .stuff = 0.456 };
This is a C only thing and doesn't exist in C++. There has been a proposal for C++20 that has been accepted, to include limited support for them: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0329r4.pdf
C++/CLI Property
The other thing that comes to mind is properties, part of managed C++.
You'd use them like that (source: https://learn.microsoft.com/en-us/cpp/extensions/property-cpp-component-extensions?view=vs-2019)
public ref class C {
int MyInt;
public:
// property data member
property String ^ Simple_Property;
// property block
property int Property_Block {
int get();
void set(int value) {
MyInt = value;
}
}
};
int C::Property_Block::get() {
return MyInt;
}
int main() {
C ^ MyC = gcnew C();
MyC->Simple_Property = "test";
Console::WriteLine(MyC->Simple_Property);
MyC->Property_Block = 21;
Console::WriteLine(MyC->Property_Block);
}
I am looking for an alternative c++ pattern to achieve this:
Read from an option from a file (let's say its either A or B).
In a cycle I want to repeat a call to a template function depending on the option, but I don't want to check the value each time, instead, I want the compiler to generate both possibilities and choose the one with template A if the option is set to A, and with template B if the option is set to B.
If i do this though:
Option option = readFromFile("AorB");
for(int i = 0; i < 100000; ++i)
{
performOperation<option>(); // Long but fast function I don't want to define twice
}
I get the following error:
error: the value of 'option' is not usable in a constant expression
How can I achieve the desired behaviour?
To make the code weirder and more meta ;) you could play a bit with variadic templates, lambdas and constexpr implicit cast:
#include <iostream>
template <char C>
struct Option {
constexpr operator char() {
return C;
}
};
template <char Opt>
void performOperation() {
std::cout << Opt << std::endl;
}
template <char... Options>
void runOption() {
char optionFromFile = 'a';
int dummy[] = {([](auto option, char chosen) {
if (chosen == option) {
for(int i = 0; i < 5; ++i) {
performOperation<option>();
}
}
}(Option<Options>{}, optionFromFile), 0)...};
static_cast<void>(dummy);
}
int main() {
runOption<'a', 'b'>();
}
[live demo]
Have fun!
As others have mentioned, you can't pass a variable to something that expects a compile time constant.
If you've got something that is either "A" or "B" and you're worried about checking for that each time then you could expand the loop/condition yourself:
Option option = readFromFile("AorB");
if(option.isA())
{
for(int i = 0; i < 100000; ++i)
{
performOperationA();
}
else
{
for(int i = 0; i < 100000; ++i)
{
performOperationB();
}
}
If you want the operation to select the behavior at runtime, then you may want to create a class to encapsulate the behavior that varies. Next create an instance of the class once based on the option value A or B. Then inside the loop, you pass the class instance to operation.
I've provided an example below that implements OptionA and OptionB in a class hierarchy. If you do it this way, then you don't even need a template at all. But you didn't provide much detail on how the behavior of your operation varies, so I didn't want to assume too much about what you have to work with. The template is only required if you have two unrelated classes that implement an identical interface.
#include <iostream>
#include <string>
class OptionType {
public: virtual int calculate( int x ) = 0;
};
class OptionA :public OptionType {
public: int calculate( int x ) { return x+99; }
};
class OptionB : public OptionType {
public: int calculate( int x ) { return x*100; }
};
template<class T>
void performOperation( T& option, int x ) {
// your performOperation is a long function
// this one is short but shows how the behavior can vary by option
std::cout << option.calculate( x ) << std::endl;
}
int main( int argc, char* argv[] )
{
// Option option = readFromFile("AorB");
// pass A or B from the command line
char option = (argc > 1) ? argv[1][0] : 'A'; // your code reads this from a file
OptionType* optionObject;
if( option == 'A' ) optionObject = new OptionA();
else optionObject = new OptionB();
for(int i = 0; i < 10; ++i)
{
performOperation( *optionObject, i );
}
}
you can't because the option is a variable, and a template is compile time. the performOperation needs to receive a constant value on the <>.
and since the operations occours on runtime - you need an if.
But you could use the branch prediction to do less work - if you sort the vector before passing to for / if call(value) else call_2(value), it would run much faster.
Template arguments must be known at compile time. At run time, it's too late to instantiate new instances of a template. You will need to force the generation of each instance that may be required at run time and implement some form of dispatching. The simplest approach is to have a dispatching function with a switch. For example :
enum class Option {
Opt1,
Opt2,
Opt3
};
template<Option opt>
void Operation() {}
void performOperation(const Option opt)
{
switch (opt)
{
case(Option::Opt1):
Operation<Option::Opt1>();
break;
case(Option::Opt2):
Operation<Option::Opt2>();
break;
case(Option::Opt3):
Operation<Option::Opt3>();
break;
default:
// Handle however you want
}
}
Another solution would use a map of std::function :
#include <map>
#include <functional>
enum class Option {
Opt1,
Opt2,
Opt3
};
template<Option opt>
void Operation() {}
const std::map<Option, std::function<void()>> func_map = {
{ Option::Opt1, []{Operation<Option::Opt1>(); }},
{ Option::Opt2, []{Operation<Option::Opt2>(); }},
{ Option::Opt3, []{Operation<Option::Opt3>(); }}
};
void performOperation(const Option opt)
{
func_map.at(opt)();
}
If I understood the question correctly.
You could try this way:
for(int i = 0; i < 100000; ++i)
{
#ifdef A
read("A");
#endif
#ifdef B
read("B");
#endif
}
and at compiler level you can choose:
g++ main.cpp -D A
or
g++ main.cpp -D B