Template function on struct members - c++

Is there a way to code a single template function able to run on different members of a given struct ?
A wrong example would look like :
struct Foo
{
int a, b;
}
template <MEMBER x> //which does not exist
cout_member(Foo foo)
{
cout << foo.x << endl;
}
int main()
{
Foo foo;
cout_member<a>(foo);
cout_member<b>(foo);
return 0;
}
I imagined an answer based on a switch, but I then wondered if this switch would be tested on run-time (what I would like to avoid) or on compile-time ?

As long as you want to pick up a data member from a set of data members having the same type, you can use a pointer to data member:
template <int Foo::*M>
void cout_member(Foo foo)
{
std::cout << (foo.*M) << std::endl;
}
And use it as:
cout_member<&Foo::a>(foo);
If you want to indicate also the type, you can do this:
template <typename T, T Foo::*M>
void cout_member(Foo foo)
{
std::cout << (foo.*M) << std::endl;
}
And use it as:
cout_member<int, &Foo::a>(foo);
Just out of curiosity, the second snippet would be even simpler in C++17:
template <auto M>
void cout_member(Foo foo)
{
std::cout << (foo.*M) << std::endl;
}
See it up and running on wandbox;

You can leverage std::mem_fn so you don't even have to care: (untested)
template < typename Fun, typename ... Params >
void print(Fun f, Params && ... p) { std::cout << f(std::forward<Params>(p)...) << "\n"; }
print(std::mem_fn(&Obj::fun), Obj());
Since you're using streams you probably don't care...but this should add little to zero overhead from just writing cout << obj.fun().
Edit: mem_fn works on data members too. Creates a callable that returns a reference to the value that you can then use: int x = mem_fn(&pair<int,char>::first)(my_pair);

Related

non-type template parameters, partial specialization vs function argument in C++

Short question;
I don't get why this syntax exists:
template <int in>
void test(){
std::cout << in << std::endl;
}
int main(){
test<5>();
return 0;
}
When you can do the same without templates:
void test(test in){
std::cout << in << std::endl;
}
int main(){
test(5);
return 0;
}
How would you do this without templates?
template<std::size_t n> void f() {
char buf[n];
}
Besides, passing values as arguments requires extra arguments, extra run-time overhead, not necessarily needed when you know a value is actually a compile-time constant. With classes, it would require an extra member, and an extra construction argument for a class which might otherwise be empty and trivial.
What you have shown is not partial specialization.
Here an example of specialization (in this case full specialization):
#include <iostream>
template <int in, int in2>
void test_template(){
std::cout << in << std::endl;
}
template <>
void test_template<1>(){
std::cout << "one" << std::endl;
}
template <>
void test_template<2>(){
std::cout << "two" << std::endl;
}
int main()
{
test_template<1>();
test_template<2>();
test_template<3>();
test_template<4>();
}
And it is useful to handle certain template parameters in a special way. (Partial specialization, is if you have multiple template arguments and specialize all except one of them)
Regarding your example, the use-case you have shown does not illustrate where it can be useful, as it indeed does not make much a difference to use a regular function there.
But if you look at functions like std::make_shared or std::make_pair there is no way how you could solve that without using templates:
template< class T1, class T2 >
std::pair<T1,T2> make_pair(T1 t, T2 u) {
return std::pair<T1,T2>(t,u);
}
They are not "the same".
The two versions of test are very different. I rename them to avoid confusion and merely list some differences:
template <int in>
void test_template(){
std::cout << in << std::endl;
}
void test_fun(test in){
std::cout << in << std::endl;
}
test_template is a template. It is not a function. For example it is not possible to get a pointer to test_template:
auto f_ptr1 = &test_template; // doesn't make sense
auto f_ptr2 = &test_fun; // OK
The template parameter has to be known at compile time:
int x;
std::cin >> x;
test_template<x>(); // error: x must be known at compile time
test_fun(x); // OK
On the other hand, once you did instantiate the template you get a function with no parameters:
auto f = &test_template<5>;
f();
auto g = &test_template<6>;
g();
Similar you can only do with test_fun when you wrap it into another function (ie overhead).
... and more.
PS: There is no partial specialization in your code.

Is there a generic way to pass pointers of overloaded methods that requires less work (than my example)

So I have a function where, using C++17, I'm able to apply any method from any object:
#include <functional>
template <typename Object, typename Method, typename ... Args>
void ApplyMethod (Object && object, Method && method, Args && ... args)
{
std::invoke(method, object, args...);
}
What I ask: Is there a way to improve this to require less work for the caller of the function when the method is overloaded.
Example use with overloaded methods:
#include <iostream>
class Foo
{
int bottles;
public:
void Edit ()
{
bottles = 666;
}
void Edit (int number)
{
bottles = number;
}
void Talk () const
{
std::cout << bottles << " bottles of beer of the wall" << std::endl;
}
};
class Bar
{
Foo foo;
void TrickEdit (int number)
{
// Because Foo::Edit is overloaded, we need to do some work:
using Method = void (Foo::*)(int);
Method ptr = &Foo::Edit;
ApplyMethod(foo, ptr, number);
}
void TrickTalk () const
{
// it's a lot neater when the method isn't overloaded:
ApplyMethod(foo, &Foo::Talk);
}
public:
void Trick ()
{
TrickEdit(900);
TrickTalk();
}
};
int main ()
{
Bar().Trick();
return 0;
}
I'm trying to perform the work at the function instead. The problem seems to lie in that &Foo::Edit has two different locations, depending on which Edit we're referring to.
In C++ FAQ - Pointers to member functions by Stroustrup and other reputable authors, I read:
Question: I need something like function-pointers, but with more flexibility and/or thread-safety; is there another way?
Answer: Use a functionoid.
Question: What the heck is a functionoid, and why would I use one?
Answer: Functionoids are functions on steroids. Functionoids are strictly more powerful than functions, and that extra power solves some (not all) of the challenges typically faced when you use function-pointers. [...] Functionoids don’t solve every problem encountered when making flexible software, but they are strictly more powerful than function-pointers and they are worth at least evaluating. In fact you can easily prove that functionoids don’t lose any power over function-pointers, since you can imagine that the old-fashioned approach of function-pointers is equivalent to having a global(!) functionoid object. Since you can always make a global functionoid object, you haven’t lost any ground. QED.
Given that the "power" of programming is basically the reduction of work duplication, and that with a normal function we would avoid the extra work at the call site that I've outlined in my problem, the FAQ answer implies that there should be a solution to this using functionoids. However, for the life of me, I can't see how functionoids would help in this case.
Maybe you can use something like that:
struct A
{
void Do() { std::cout << "Do no parm" << std::endl; }
void Do(int) { std::cout << "Do 1 parm" << std::endl; }
void Do(int,int) { std::cout << "Do 2 parms" << std::endl; }
};
template < typename OBJ_TYPE, typename ... ARGS >
auto Invoke( OBJ_TYPE&& obj, void( std::remove_reference<OBJ_TYPE>::type::* func)(ARGS...), ARGS&& ... args )
{
return std::invoke( func, obj, args... );
}
int main()
{
A a;
Invoke( a, &A::Do);
Invoke( a, &A::Do, 1);
Invoke( a, &A::Do,1,2);
}
The idea is simply to fix the pointer type of the member function pointer to the given arguments in the parameter pack.
If someone has an idea how to automatically determine the return type, so that we also can use overloads with different return types, that would be very funny! I end up in a recursion :-)
If we simply specify the return type, we can use it as follows:
struct A
{
void Do() { std::cout << "Do no parm" << std::endl; }
void Do(int) { std::cout << "Do 1 parm" << std::endl; }
int Do(int,int) { std::cout << "Do 2 parms" << std::endl; return 42;}
};
template < typename RETURN_TYPE, typename OBJ_TYPE, typename ... ARGS >
auto Invoke( OBJ_TYPE&& obj, RETURN_TYPE( std::remove_reference<OBJ_TYPE>::type::* func)(ARGS...), ARGS&& ... args )
{
return std::invoke( func, obj, args... );
}
int main()
{
A a;
Invoke<void>( a, &A::Do);
Invoke<void>( a, &A::Do, 1);
int retval = Invoke<int>( a, &A::Do,1,2);
std::cout << retval << std::endl;
}
You can write a variable template that specifies what Args... should be.
template <typename... Args>
struct Overload {
template<typename R, typename O>
operator R(O::*)(Args...) (R(O::*p)(Args...)) const { return p; }
template<typename R, typename O>
operator R(O::*)(Args...) const (R(O::*p)(Args...) const) const { return p; }
};
template <typename... Args>
Overload overload;
Which is used like
struct A
{
void Do() { std::cout << "Do no parm" << std::endl; }
void Do(int) { std::cout << "Do 1 parm" << std::endl; }
void Do(int,int) { std::cout << "Do 2 parms" << std::endl; }
};
template <typename Object, typename Method, typename ... Args>
void ApplyMethod (Object && object, Method && method, Args && ... args)
{
std::invoke(method, object, args...);
}
int main()
{
A a;
ApplyMethod( a, overload<>(&A::Do));
ApplyMethod( a, overload<int>(&A::Do), 1);
ApplyMethod( a, overload<int, int>(&A::Do),1,2);
}
This is what Qt does for it's modern signals and slots.

Is it possible to store lambdas with different signatures in a std::vector and execute them (with their respective arguments) in a function?

I am creating a class that allows me to store lambdas that need to be executed (in order) at a point in the future.
class Promise{
private:
//snip//
std::vector<std::function<void()>> lchain;
public:
//snip//
void then(const std::function<void()> &f){
if (this->resolved) {//If the promise is resolved we just call the newly added function, else we add it to the lchain queue that will be processed later
f();
return;
}
lchain.push_back(f);
}
void launch(){
this->resolved = true;
for (auto &fun: this->lchain)
fun();
}
}
It is obvious that it will only work with lambdas with a signature like [&](){} but some of the tasks need to work with an arbitrary number of parameters of arbitrary types (both, parameters and types are known in advance, when the function is added to the queue).
An example driver program that currently works is
int main(){
Promise* p = new Promise([](){
std::cout << "first" << std::endl;
})->then([](){
std::cout << "second" << std::endl;
});
Promise->launch(); //In my code promise chains are picked up by worker threads that will launch them.
}
An example program I would like to execute:
int main(){
Promise* p = new Promise([](){
return 5;
})->then([](int n){
return n*n;
})->then([](int n){
std::cout << n << std::endl; //Expected output: 25
});
Promise->launch();
}
Things that I am struggling to do:
Storing lambdas of mixed signatures in a std::vector
Making the then() method call f with the arguments associated with f
Making the then() function return the result of f so it can be fed to the next lambda in the chain (preferably binding it before storing the lambda in the vector)
I have been searching in stackoverflow the whole day but the closest I got was this but I would like something that can be done in the then() method to simplify the program code as it would be a pain to bind every single lambda before calling the then() method.
I have something that I think does what you want. I'll start with an example and then introduce the implementation.
int main(){
Promise p([] {
return 5;
});
p.then([](int n) {
return n*n;
}).then([](int n) {
std::cout << n << '\n';
});
p.launch();
struct A { int n; };
struct B { int n; };
struct C { int n; };
Promise q([](A a, int n) {
std::cout << "A " << a.n << ' ' << n << '\n';
return B{2};
});
q.then([](B b) {
std::cout << "B " << b.n << '\n';
return C{3};
}).then([](C c) {
std::cout << "C " << c.n << '\n';
});
q.launch(A{1}, 111);
Promise<B(A, int)> r([](auto a, int n) {
std::cout << "A " << a.n << ' ' << n << '\n';
return B{5};
});
r.then([](auto b) {
std::cout << "B " << b.n << '\n';
return C{6};
}).then([](auto c) {
std::cout << "C " << c.n << '\n';
});
r.launch(A{4}, 222);
}
This outputs:
25
A 1 111
B 2
C 3
A 4 222
B 5
C 6
Some drawbacks:
Calling then after the promise has been resolved doesn't automatically call the function. Things get confusing in that situation and I'm not even sure if it's possible.
You can't call then multiple times on the same promise. You have to build a chain and call then on the result of the previous then.
If any of those drawbacks make this unusable, then you can stop reading this humongous answer.
The first thing we need is a way of getting the signature of a lambda. This is only used for the deduction guide so it isn't strictly necessary for the core concept to work.
template <typename Func>
struct signature : signature<decltype(&Func::operator())> {};
template <typename Func>
struct signature<Func *> : signature<Func> {};
template <typename Func>
struct signature<const Func> : signature<Func> {};
template <typename Ret, typename... Args>
struct signature<Ret(Args...)> {
using type = Ret(Args...);
};
template <typename Class, typename Ret, typename... Args>
struct signature<Ret (Class::*)(Args...)> : signature<Ret(Args...)> {};
template <typename Class, typename Ret, typename... Args>
struct signature<Ret (Class::*)(Args...) const> : signature<Ret(Args...)> {};
template <typename Func>
using signature_t = typename signature<Func>::type;
The next thing we need is a base class. We know the next promise must accept the return type of the current promise as an argument. So we know the argument type of the next promise. However, we don't know what the next promise will return until then is called so we need a polymorphic base to refer to the next promise.
template <typename... Args>
class PromiseBase {
public:
virtual ~PromiseBase() = default;
virtual void launch(Args...) = 0;
};
Now we have the Promise class itself. You can construct a promise with a function. As I alluded to above, a promise stores a pointer to the next promise in the chain. then constructs a promise from the given function and stores a pointer to it. There is only one next pointer so you can only call then once. There's an assertion to make sure this doesn't happen. launch calls the stored function and passes the result to the next promise in the chain (if there is one).
template <typename Func>
class Promise;
template <typename Ret, typename... Args>
class Promise<Ret(Args...)> : public PromiseBase<Args...> {
public:
template <typename Func>
explicit Promise(Func func)
: handler{func} {}
template <typename Func>
auto &then(Func func) {
assert(!next);
if constexpr (std::is_void_v<Ret>) {
using NextSig = std::invoke_result_t<Func>();
auto nextPromise = std::make_unique<Promise<NextSig>>(func);
auto &ret = *nextPromise.get();
next = std::move(nextPromise);
return ret;
} else {
using NextSig = std::invoke_result_t<Func, Ret>(Ret);
auto nextPromise = std::make_unique<Promise<NextSig>>(func);
auto &ret = *nextPromise.get();
next = std::move(nextPromise);
return ret;
}
}
void launch(Args... args) override {
if (next) {
if constexpr (std::is_void_v<Ret>) {
handler(args...);
next->launch();
} else {
next->launch(handler(args...));
}
} else {
handler(args...);
}
}
private:
using NextPromise = std::conditional_t<
std::is_void_v<Ret>,
PromiseBase<>,
PromiseBase<Ret>
>;
std::unique_ptr<NextPromise> next;
std::function<Ret(Args...)> handler;
};
Finally, we have a deduction guide.
template <typename Func>
Promise(Func) -> Promise<signature_t<Func>>;
Here's an online demo.

enable_if: minimal example for void member function with no arguments

I am trying to get a better understanding of std::enable_if in C++11 and have been trying to write a minimal example: a class A with a member function void foo() that has different implementations based on the type T from the class template.
The below code gives the desired result, but I am not understanding it fully yet. Why does version V2 work, but not V1? Why is the "redundant" type U required?
#include <iostream>
#include <type_traits>
template <typename T>
class A {
public:
A(T x) : a_(x) {}
// Enable this function if T == int
/* V1 */ // template < typename std::enable_if<std::is_same<T,int>::value,int>::type = 0>
/* V2 */ template <typename U=T, typename std::enable_if<std::is_same<U,int>::value,int>::type = 0>
void foo() { std::cout << "\nINT: " << a_ << "\n"; }
// Enable this function if T == double
template <typename U=T, typename std::enable_if<std::is_same<U,double>::value,int>::type = 0>
void foo() { std::cout << "\nDOUBLE: " << a_ << "\n"; }
private:
T a_;
};
int main() {
A<int> aInt(1); aInt.foo();
A<double> aDouble(3.14); aDouble.foo();
return 0;
}
Is there a better way to achieve the desired result, i.e. for having different implementations of a void foo() function based on a class template parameter?
I know this wont fully answer your question, but it might give you some more ideas and understanding of how you can use std::enable_if.
You could replace your foo member functions with the following and have identical functionality:
template<typename U=T> typename std::enable_if<std::is_same<U,int>::value>::type
foo(){ /* enabled when T is type int */ }
template<typename U=T> typename std::enable_if<std::is_same<U,double>::value>::type
foo(){ /* enabled when T is type double */ }
A while back I gained a pretty good understanding of how enable_if works, but sadly I have forgotten most of its intricacies and just remember the more practical ways to use it.
As for the first question: why V1 doesn't work? SFINAE applies only in overload resolution - V1 however causes error at the point where type A is instantiated, well before foo() overload resolution.
I suppose there are lot's of possible implementations - which is the most appropriate depends on an actual case in question. A common approach would be to defer the part of A that's different for different template types to a helper class.
template <typename T>
class A_Helper;
template <>
class A_Helper<int> {
public:
static void foo( int value ){
std::cout << "INT: " << value << std::endl;
}
};
template <>
class A_Helper<double> {
public:
static void foo( double value ){
std::cout << "DOUBLE: " << value << std::endl;
}
};
template <typename T>
class A {
public:
A( T a ) : a_(a)
{}
void foo(){
A_Helper<T>::foo(a_);
}
private:
T a_;
};
The rest of A can be declared only once in a generic way - only the parts that differ are deferred to a helper. There is a lot of possible variations on that - depending on your requirements...

Accessing individual types of variadic templates

I am creating a lua binding in C++11. I want to process each type in a variadic template.
I was thinking I could do something like this, except using Params... represents all of the types inside of it, and not a the next single type inside of it like variadic function parameters do.
template <class T, typename ReturnType, typename... Params>
struct MemberFunctionWrapper <ReturnType (T::*) (Params...)>
{
static int CFunctionWrapper (lua_State* luaState)
{
for(int i = 0; i < sizeof...(Params); i++)
{
//I want to get the next type, not all of the types
CheckLuaValue<Params...>();
//Do other stuff
}
}
};
How would I go about doing this?
You can do this by simply expanding after the function call, into something that can be expanded to.
// put this in your namespace
struct Lunch { template<typename ...T> Lunch(T...) {} };
// and this instead of the for loop
Lunch{ (CheckLuaValue<Params>(), void(), 0)... };
You can do something else with a lambda. You can even have your i incremented
static int CFunctionWrapper (lua_State* luaState)
{
int i = 0;
Lunch{
(CheckLuaValue<Params>(),
[&]{ std::cout << "That was param " << i << std::endl; }(),
++i)...
};
}
Note that the Standard supports putting everything into the lambda. Compiler support until recently (last time I checked) wasn't very good though
static int CFunctionWrapper (lua_State* luaState)
{
int i = 0;
Lunch{([&]{
CheckLuaValue<Params>();
std::cout << "That was param " << i << std::endl;
}(), ++i)...
};
}