Struct and Tuple template parameters in D - templates

Is it possible to write a single templated function to increment the (numeric) fields of different structs? For example:
struct Color
{
ubyte a,r,g,b;
}
struct Point
{
double x, y;
}
I tried something like this:
T update(T, A)(T t, A a)
if (is(T == struct))
{
auto vals = t.tupleof;
foreach (i; 0 .. vals.length) {
vals[i] += a; // error: i cannot be read at compile time
}
return T(vals); // convert back to struct
}
I have also tried writing function templates that accept tuples, but the tuples are always expanded, which prevents the compiler from matching the correct template.
Thanks.

Well, I'd say that what you're trying doing is rather bizarre, but it's certainly possible. The most naive, in-place way would probably be:
void update(T)(ref T t)
if(is(T == struct))
{
foreach(ref var; t.tupleof)
++var;
}
The simplest way to do it with a copy would probably be to copy it and then update it rather than trying to construct a new one with updated values (though I'm sure that that can be done too if you really want to):
T update(T)(T t)
if(is(T == struct))
{
auto copy = t;
foreach(ref var; copy.tupleof)
++var;
return copy;
}
The main problem here, of course, is that the template constraint on both of these is far too weak. All you have to do is have unincrementable types in your struct, and it won't work. The simplest way to fix that would probably be to create an eponymous template to test it for you:
T update(T)(T t)
if(isIncrementableStruct!T)
{
auto copy = t;
foreach(ref var; copy.tupleof)
++var;
return copy;
}
template isIncrementableStruct(T)
{
enum isIncrementableStruct = is(T == struct) &&
is(typeof({T t; foreach(var; t.tupleof) ++var;}));
}
And if you want to be able to increment all of the fields that are incrementable and leave the others alone, you'd probably do something like:
T update(T)(T t)
if(is(T == struct))
{
auto copy = t;
foreach(ref var; copy.tupleof)
{
static if(canIncrement!(typeof(var)))
++var;
}
return copy;
}
template canIncrement(T)
{
enum canIncrement = is(typeof({T var; ++var;}));
}
In any case, the main thing that you appear to have missed was to attempt iterating over tupleof directly while using ref so that the elements were updated rather than having copies of them being updated.

Related

Can't manage to figure out the syntax of C++ lamda expression as a method's parameter

Question:
How do you pass a lambda expression into a function. for example:
int GetCoolInt()
{
int a = 3;
return AddToInt( [a] (int b) {
a += b;
});
}
int AddToInt(int func(int output))
{
return func(3);
}
int output = GetCoolInt();
Context of my issue:
I have the following 2 methods:
FindPlayerStartByTag calls FindActor to use logic that will be used in other methods.
//template <typename T>
APlayerStart* FindPlayerStartByTag(FName tag)
{
return FindActor<APlayerStart>(tag, [tag](TObjectIterator<APlayerStart> actor) {
APlayerStart* playerStart;
if (actor->PlayerStartTag == tag)
{
playerStart = *actor;
}
return playerStart;
});
}
This method is the logic to find a specific object in an iterator with the help of the FindPlayerStartByTag logic
template <typename T>
T* FindActor(FName tag, T* func(TObjectIterator<T> actor))
{
T* returnValue;
if (!tag.IsNone())
{
// Search for actor
for (TObjectIterator<T> itr; itr; ++itr)
{
if (itr->IsA(T::StaticClass()))
{
returnValue = func(itr);
if (returnValue)
{
break;
}
}
}
}
return returnValue;
}
I currently have this error:
I'm confused as to what it means, considering a third method:
template <typename T>
T* FindActorByTag(FName tag)
{
return FindActor<T>(tag, [tag](TObjectIterator<AActor> actor)
{
T* foundActor;
for (FName currentActorTag : actor->Tags)
{
if (tag == currentActorTag)
{
foundActor = *actor;
}
}
return foundActor;
});
}
compiles just fine.
I can see that by adding template <typename T> gets rid of the error (see the //template <typename T>, but i don't need this as in the case of APlayerStart, i am already aware of what type the method needs to be.
Anyone help explain this?
Thanks!
Edit:
Here is a version of the method that i was using before i refactored into here:
APlayerStart* FindPlayerStartByTag(FName tag)
{
/*return FindActor<APlayerStart>(tag, [tag](TObjectIterator<APlayerStart> actor) {
APlayerStart* playerStart;
if (actor->PlayerStartTag == tag)
{
playerStart = *actor;
}
return playerStart;
});*/
APlayerStart* returnValue;
if (!tag.IsNone())
{
// Search for actor
for (TObjectIterator<APlayerStart> itr; itr; ++itr)
{
if (itr->IsA(APlayerStart::StaticClass()) && itr->PlayerStartTag == tag)
{
returnValue = *itr;
}
}
}
return returnValue;
}
but compiles.
Edit 2:
This is how i intend on using the methods:
PlayerStart = ActorHelper->FindPlayerStartByTag(PlayerStartTag);
ATreasureChestActor* treasureChestActor = ActorHelper->FindActorByTag<ATreasureChestActor>(TreasureActorTagName);
Edit 3:
The issue seems to be coming from the closure usage!
This is with the use of a closure variable:
and this is without:
Your post is still a mess, with 4 different versions of the same issue. I will focus on the first code snippet as it seems to be the closest one to a [MCVE] and I will clarify how to properly use lambdas and function objects.
int AddToInt(int func(int output))
This is a little bit misleading. I suggest changing it to the equivalent, but more used:
int AddToInt(int (*func)(int))
This means: declaring a function named AddToInt which:
accepts a parameter of type "pointer to function accepting an int and returning an int" and
returns an int.
As you can see, your function accept a classic C function pointer. It won't accept a function object of any type. To note here is that lambdas without capture can be converted to a function pointer.
For instance keeping the above declaration:
AddToInt([](int b) { return b + 1; }); // ok, non-capturing lambda conversion to function pointer
AddToInt([a](int b) { return a + b; }); // error cannot convert capturing lambda to function pointer
The reason is simple to understand. A non-capturing lambda can be equivalent to a free function, but a capturing lambda has a state (formed by the capture set), so it is "more" than a simple, classical free function.
As you can see, accepting function pointers is very much an archaic idiom because of these limitations (and don't even think of passing any kind of function object - e.g. a class with operator() defined).
For accepting any kind of callable object you generally have two options: the general template or the standard std::function object.
Template object
template <class Fn>
int AddToInt1(Fn func)
{
return func(3);
}
Now you can call AddToInt1 with any kind of callable. Depending of the type of the deduced Fn type you can have zero overhead with this method. A downside is that you can accept any type, including non-callable ones, or ones with incorrect parameter or return types. Concepts will alleviate most of these downsides.
AddToInt1([](int b) { return b + 1; }); // OK
AddToInt1([a](int b) { return a + b; }); // OK
You also might want to add perfect forwarding (omitted in the example for brevity).
std::function
The other route is to use std::function:
int AddToInt2(std::function<int(int)> func)
The disadvantage here is the heaviness of the std::function object. It uses type erasure and that adds a significant amount of performance penalty (which can be perfectly acceptable depending on your usage).
AddToInt2([](int b) { return b + 1; }); // OK
AddToInt2([a](int b) { return a + b; }); // OK
Now, once you get the gist of the above there are some more problems with your code you need to figure out:
[a] (int b) { a += b;};
First of all, are you aware that this lambda does not return anything? Furthermore it tries to modify the captured by value a which is illegal, as the lambda's operator() is const by default for good reason. If you want the lambda to modify the outer a captured variable, then you need to capture it by reference:
[&a] (int b) { a += b;};
And now you have to really really be careful to not end up with a dangling reference.
But I suspect you meant:
AddToInt([a] (int b) { return a + b;});
But that is just pure speculation on my part.
Here is a fully working example:
template <class Fn>
int AddToInt1(Fn func)
{
return func(3);
}
int AddToInt2(std::function<int (int)> func)
{
return func(3);
}
int GetCoolInt()
{
int a = 3;
return AddToInt1([a] (int b) { return a + b;}); // OK
//return AddToInt2([a] (int b) { return a + b;}); // OK
}
There are some important points I just mentioned here, but elaborating on them would be equivalent to writing a full tutorial on lambdas and beyond, which is out of the scope of this site. In conclusion you have to study the subject on your own.

How to have the compiler deduce the return type of a templated method in C++11?

I have a templated-method where the return-type is will be the result of a reinterpret_cast<>()-call.
class A {
void *_ptr;
public:
template<typename T>
T buffer() { return reinterpret_cast<T>(_ptr); }
};
This way makes me use the <>-syntax when calling this function:
A a;
auto b = a.buffer<double *>();
I'd prefer to call this method without the template arguments and let the compiler deduce the return type, based on the variable-type.
A a;
double *out = a.buffer();
Is this possible with return-type deduction?
I tried using auto, the->-operand and the trailing return type syntax.
auto buffer() -> decltype(reinterpret_cast<T>(_ptr)) const
{ return reinterpret_cast<T>(_ptr); }
but it still doesn't work.
Is there any way doing this, in C++11?
Yes, but only via a proxy type having a conversion function template:
struct BufferProxy {
void* ptr;
template<class T> operator T*() { return reinterpret_cast<T*>(ptr); }
};
BufferProxy buffer() { return BufferProxy{_ptr}; }
Example.
Note that users who have become familiar with the use of auto for return type deduction are likely to become confused by this technique:
auto out = a.buffer(); // out is BufferProxy
auto* out = a.buffer(); // fails to compile; can't deduce 'auto*' from 'a.A::buffer()'
Up until C++17, you can prevent auto out = a.buffer(); from compiling by giving BufferProxy a deleted copy constructor (and perhaps returning it by aggregate construction: return {_ptr};), but the user could still use auto&& and from C++17 guaranteed copy elision will make the auto form work again.
You may want a class something like the following. This would seem to offer most of what you want to do.
One issue I was wondering about was how to determine if a pointer stored into the class was the same type or not. So I thought it would be best to add an additional method to check the typeid() using the hash_code() method.
So the class I came up with using the operator idea of #ecatmur in his/her answer:
class A {
void *_ptr;
size_t _ptrHash;
public:
template<typename T> operator T*() { return reinterpret_cast<T *>(_ptr); }
template<typename T>
void SetPtr(T *p) { _ptr = p; _ptrHash = typeid(*p).hash_code(); }
template<typename T> bool operator == (T *p) { return p && typeid(*p).hash_code() == _ptrHash /* && p == _ptr */; }
};
The equality operator could either check only the type as above or if you uncomment the additional check, also check for value of the pointer. You probably just want to check for the type.
A simple demo function that I used to test this out was as follows:
void funky1() {
A a;
double ddd[50] = { 0.0 };
ddd[0] = 5.0; ddd[2] = 7.0;
a.SetPtr(&ddd[0]);
double *p = a;
bool bb = a == p;
long lll[50] = { 0 };
lll[0] = 5; lll[2] = 7;
long *q = a;
bb = a == q;
a.SetPtr(&lll[0]);
q = a;
bb = a == q;
}
I stepped through this with the debugger, Visual Studio 2013, and it looked like it worked like a champ.
I guess this answer is the most elegant.
Anyway, you can also let the class initializes your pointer as it follows:
class A {
void *_ptr;
public:
template<typename T>
void buffer(T **t) { *t = reinterpret_cast<T*>(_ptr); }
};
int main() {
A a;
double *b;
a.buffer(&b);
}
This way the type is deduced from the parameter list and you have not to explicitly specify it.

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

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

How to combine negation with declaration inside if-statement?

When using C-style return codes to signal errors, it's pretty common to see code like this:
if (do_something()) {
do_something_else();
} else {
report_failure();
}
Sometimes, if one block is much larger than the other, you might want to reorder the "handle failure" block before the "do_something_else" block.
if (!do_something()) {
report_failure();
} else {
do_something_else();
}
(Or, when it really is C-code the codes may be such that 0 indicates success rather than failure, but let's ignore that.)
When I use C++ idioms like boost::optional or one of the proposed std::expected types, usually what I want to do is put a declaration inside the condition of the if statement:
if (auto ok = do_something()) {
do_something_else(*ok);
} else {
report_failure(ok.error());
}
I like to do this because this way, ok is strictly contained in scope, it's not visible outside the two blocks.
However, once I do it this way, I can't reorder the two branches if I want, which probably annoys me much more than it should, but still.
What I would really like is a syntax
if not (auto ok = do_something()) {
report_failure(ok.error());
} else {
do_something_else(*ok);
}
But to my knowledge that doesn't actually work.
Is there a trick to accomplish that?
C++17 will introduce this syntax:
if (auto ok = do_something(); !ok) {
report_failure(ok.error());
} else {
do_something_else(*ok);
}
Which is basically what you want.
It is in the feature-complete draft.
You can add an extra scope:
{
auto ok = do_something();
if (! ok) {
report_failure(ok.error());
} else {
do_something_else(*ok);
}
}
Personally I wouldn't add those braces as the scope should be clear from the rest of the code, if you have too much functionality in one function you should refactor the code anyways...
Alright, so here's a little class that does what you want. Dress it up however you like.
template <typename T>
struct not_optional_type: public optional <T>
{
typedef optional <T> base_type;
not_optional_type( const base_type& v ): base_type( v ) { }
operator bool () const { return !(base_type)(*this); }
T operator * () const { return *(base_type)(*this); }
};
template <typename T>
not_optional_type <T>
not_optional( const optional <T> && v )
{
return not_optional_type <T> ( v );
}
Use it as you would expect:
if (auto ok = not_optional( do_something() ))
fooey();
else
success( *ok );
I personally think the proposed if syntax modification is an abomination.
Well, a lot of dirty tricks come to mind involving macros, but, supposing you don't want to go there, here's a non-macro trick:
template <class T> class notter {
T d_t;
public:
notter(T &t) : d_t(t) {}
notter(T t) : d_t(t) {}
operator bool() { return !d_t; }
T &data() { return d_t; }
};
Now you can use it as:
if (notter<int> a = do_something()) {
report_failure();
}
else {
do_something_else(a.data());
}
This assumes that do_something returns an int. You may avoid naming the type with decltype like this:
if (notter<decltype(do_something())> a = do_something()) {
but in cases like this, that may be overkill.
You may tweak it to your needs, if, say, data() is too verbose for you, or you want just one of the constructors, or to make a more "drop-in replacement" for optional<> (as per comments from Duthomhas) or expected<> - you may employ template specialization.
Also, you can take hint from std::make_shared() and such:
template<class T> notter<T> make_notter(T t) { return notter<T>(t); }
and use it like:
if (auto a = make_notter(do_something())) {

Augment a class / apply an aspect in pure C++ (C++11)

Suppose I have a class:
class Widget {
public:
void initialize() {
// hurr-durr
};
int computeAnswer() {
return -42;
};
std::string getQuestion() {
return "The question";
};
};
It performs some computation, can do whatever it wants.
Now I want to augment it - apply an aspect, say one that logs each method call.
If I implemented this by hand, I'd implement all methods in this fashion:
int LoggingWidget::computeAnswer(){
log << 'Calling method computeAnswer';
int result = Widget::computerAnswer();
log << 'Result = ' << result;
return result;
}
I'd like the solution to be as generic as possible (I don't want to manually forward all calls), so the possible usages could include one of these (whichever is possible)
Widget* w = new LoggingWidget(); // either a class that inherits from Widget
// and automatically forwards all calls.
Widget* w = new Logging<Widget>(); // or a template that does this.
so that when I call
int result = w.computeAnswer();
The calls will be logged. Perhaps the new ellipsis operator (...) could come in handy here?
This isn't directly possible, since you can't inspect a class to see which members it has.
However, you can do something close:
Logging<Widget> w(widget);
w([&](Widget& w){
return w.computeAnswer();
});
Where Logging::operator() looks like follows:
/* somewhere in class: T wrapped; */
template<class F>
auto operator()(F&& f)
-> decltype(f(wrapped))
{
pre_log();
auto&& result = f(wrapped);
post_log(result);
return result;
}
It won't get better much better than this for totally generic code, since C++ has no (static) reflection.
Expanding on Xeo's answer, if you use decltype or result_of rather than auto && you also get copy elision.
template<typename F>
auto operator()(F &&f) -> decltype(std::forward<F>(f)(wrapped))
{
pre_log();
decltype(std::forward<F>(f)(wrapped)) result = std::forward<F>(f)(wrapped);
post_log(result);
return result;
}
In C++14 you can shorten this to:
template<typename F>
decltype(auto) operator()(F &&f)
{
pre_log();
decltype(auto) result = std::forward<F>(f)(wrapped);
post_log(result);
return result;
}