I have an exercise where I need to write a function. Function scheme look like
auto add(int a){
}
I need to be able to call this function with many brackets:
add(1)(2)(3); // 6
add(1)(2)(3)(4); // 10
add(1)(2)(3)(4)(5); // 15
But I can not figure out which C++ feature I should use in this case. I heard that I should use functors but I don't know if this is the best idea in this case.
You can do it by having add return a functor, i.e., an object that implements operator(). You can write a templated version that will let the compiler deduce the type. Try it here.
template <class T>
struct adder
{
T val;
adder(T a) : val(a) {}
template <class T2>
auto operator()(T2 a) -> adder<decltype(val + a)> { return val + a; }
operator T() const { return val; }
};
template <class T>
adder<T> add(T a)
{
return a;
}
Example
In this example, T will ultimately resolve to double:
std::cout << add(1)(2.5)(3.1f)(4) << std::endl;
// T is int -----^
// T is double ------^
// T is still double -----^
// T is still double ----------^
Here is another example where T will resolve to double:
std::cout << add(1)(2.5f)(3.1)(4) << std::endl;
// T is int -----^
// T is float -------^
// T is double ------------^
// T is still double ----------^
Explicit Constructor
If you want the constructor of adder to be explicit you also have to change the return statements slightly.
template <class T>
struct adder
{
T val;
explicit adder(T a) : val(a) {}
template <class T2>
auto operator()(T2 a) -> adder<decltype(val + a)>
{
return adder<decltype(val + a)>(val + a);
}
operator T() const { return val; }
};
template <class T>
adder<T> add(T a)
{
return adder<T>(a);
}
The only solution that comes to my head is make this "add" as some class object with overloaded brackets operator, which will return new object, and then call new brackets from it, but you will need to return final value from it somehow, like some getter func.
class Adder{
private:
int value;
public:
Adder():value(0){}
Adder(int a):value(a){}
int get(){return value;}
Adder operator() (int a) {
return Adder(value+a);
}
};
But it doesn't seem as something useful, probably there is better way to accomplish what you want to get.
Related
Let's say I have the following class:
template <typename T>
class SomeClass : Parent<T>
{
public:
// I have a function such as this one:
T DoSomething(const T &t)
{
return t.DoSomething(some_data);
}
// But `T` might be a pointer, so sometimes I will need something like the following
// instead (which obviously doesn't work as given):
T DoSomething(const T &t)
{
return new T(t->DoSomething(some_data));
}
private:
XYZ some_data;
};
I got stuck in a giant mess of template errors trying to implement this in any semi-nice way possible using template specialization.
In the end I came up with this very ugly solution:
template <typename T>
class SomeClass : Parent<T>
{
public:
T DoSomething(const T &x)
{
return Specializer<T>::Do(this, x);
}
private:
template <typename V>
struct Specializer {
static V Do(SomeClass *me, const V &x)
{
return x.DoSomething(me->some_data);
}
};
template <typename V>
struct Specializer<V*> {
static V* Do(SomeClass *me, const V *&x)
{
return new V(x->DoSomething(me->some_data));
}
};
XYZ some_data;
};
Is there a better way to do this that doesn't involve stuffing this function into a dummy class/struct and passing around my this pointer?
PS: In reality, this has nothing to do with pointers, but rather with different types of containers. Pointers were just an easy example to use here.
You can avoid writing any specializations, and use a type trait like std::is_pointer along with if constexpr to decide what code to execute depending on the whether the type is a pointer type or not:
auto DoSomething(const T &t)
{
if constexpr (std::is_pointer_v<T>)
return new T(t->DoSomething(some_data));
else
return t.DoSomething(some_data);
}
If you don't want to check for whether T is a pointer, but want to check something else, you can still use this pattern by dropping in a suitable replacement for is_pointer.
If you have access to c++20, you can clean up the need for any SFINAE, specializations, or if constexpr by using concepts and constraints instead. This just allows you to define the same function N times with different criteria for its insantiation, which is much more readable IMO.
This is almost the same as the SFINAE approach, but without the need for the awful syntax (no std::declval, decltype, etc). It also doesn't require all implementations to exist in one function definition like the if constexpr approach; all you need is separate function definitions with different requires clauses:
#include <concepts>
...
template <typename T>
class SomeClass : Parent<T>
{
public:
// Work for everything that's not specialized
void DoSomething(const T &t)
{
std::cout << "Basic overload" << std::endl;
}
// Only work for pointers
void DoSomething(const T& t) requires(std::is_pointer_v<T>)
{
std::cout << "Pointer overload" << std::endl;
}
// Only work if T is convertible to SomeType
void DoSomething(const T& t) requires(std::convertible_to<T, SomeType>)
{
std::cout << "Convertible to SomeType overload" << std::endl;
}
private:
XYZ some_data;
};
Live Example
In this approach there are 3 different entries:
The basic fallback for all templates
An implementation that works for any pointer type, and
An implementation that works for any T type that may be convertible to SomeType
What about using SFINAE?
For example
#include <utility>
#include <iostream>
template <typename>
struct Parent
{ };
using XYZ = int;
template <typename T>
class SomeClass : Parent<T>
{
public:
template <typename U = T>
auto DoSomething (T const & t)
-> decltype( std::declval<U>().DoSomething(std::declval<XYZ>()) )
{ std::cout << "ref\n"; return t.DoSomething(some_data); }
template <typename U = T>
auto DoSomething (T const & t)
-> std::remove_reference_t<
decltype( std::declval<U>()->DoSomething(std::declval<XYZ>()),
std::declval<T>() )>
{
using V = std::remove_reference_t<decltype(*t)>;
std::cout << "pnt\n"; return new V(t->DoSomething(some_data));
}
private:
XYZ some_data;
};
struct foo
{
foo (foo*) {}
foo () {}
foo DoSomething (int) const { return {}; }
} ;
int main()
{
SomeClass<foo> sc1;
SomeClass<foo*> sc2;
foo f;
sc1.DoSomething(f);
sc2.DoSomething(&f);
}
I mean: what about enabling the first version if, and only if, T is a type that supports a DoSomething(XYZ) method and enabling the second version if, and only if, T is a pointer of a type that supports a DoSomething(XYZ) method?
Suppose that a class has a member function which should accept either a double(double) function or a class instance with a "MyStructFunc" public member function as an argument:
#include<functional>
#include <type_traits>
struct Caller
{
// (1.)
double call(std::function<double(double)> func) { return func(1); }
// (2.)
template<typename T>
double call(const T& S) { return S.MyStructFunc(2); }
};
So, for example, we can pass
double myFunc(double x) { return x * x * x; }
or
struct myStruct
{
double MyStructFunc(double x) const { return x * x; }
};
like this:
int main()
{
Caller c;
myStruct ms;
c.call(myFunc);
c.call(ms);
}
Unfortunately, I get an error. Could you please help me make it work? Thank you for your help!
function pointer is not a std::function, so your template method is a better match.
You might use SFINAE to restrict your template method:
// (2.)
template<typename T>
auto call(const T& S) -> decltype(S.MyStructFunc(2)) { return S.MyStructFunc(2); }
Demo
I want to write a function in c++ that takes a variable of type int and what it does is that it will define the overloading operator () of a functor and will return that functor as output argument. For example:
template<class Functor>
Functor myFunc(double n)
{
Functor f;
double Functor::operator() (double q)
{ return n*q;}
return Functor;
}
class myClass
{
double operator() ( double q ) const ;
};
Is this proper the way of doing it ?
There's a syntactic sugar for what you're trying to do (wrongly). It's called lambda expressions and this is what it should look like:
auto myFunc(double n)
{
return [n](double q) { return n * q; }
}
If C++11 is not available, you can emulate it like this (which fixes your errors above):
class Functor
{
double m_n;
public:
Functor(double n) : m_n(n) {}
double operator()(double q) const { return m_n * q; }
};
Functor myFunc(double n)
{
return Functor(n);
}
If you wish, you can keep myFunc as a template, but the point is, you can change the behaviour by the functor you pass in, so trying to hardcode operator() inside myFunc does not really make sense, and is not possible.
Making it more generic:
template <typename T>
class Functor
{
T m_n;
public:
Functor(T n) : m_n(n) {}
T operator()(T q) const { return m_n * q; }
};
template <template <typename> class Functor, typename T>
auto myFunc(T n)
{
// we can use perfect forwarding here, but it's far beyond the original question
return Functor<T>(n);
}
Usage:
myFunc<Functor>(2)(3)
Even more generic, for variable amount of parameters captured by a functor (variadic templates):
template <template <typename ...> class Functor, typename ... Ts>
auto myFunc(Ts ... ns)
{
return Functor<Ts...>(ns...);
}
Basically, what I want to do is to hava a wrapper on some abstract class, then have the same wrapper class wrap around the output of any member function of that class. Keep doing that so that all objects are always wrapped.
Like (presudocode)
wrap<set(1..10)> (multiply,2)
(divide,3)
(plus,5)
(inverse)
(collect first 10)
.unwrap()
All lines above except the last line outputs wrap of something. It seems to be meanling less for now, but I believe then we can apply interesting things on it like:
wrap<someClass> dat;
dat.splitIntoThreads(2)
(thingA) .clone()
(thingB) (thing1)
(thingC) (thing2)
(thingD) (thing3)
.nothing() (thing4)
.sync() .exit()
.addMerge()
Here is my code for wrap:
template<class T>
struct wrap{
wrap(){}
wrap(T b){a=b;}
template<class L,class...R>
L operator() (L(T::*f)(R...),R...r){
return a.f(r...);
}
T a;
};
int main(){
wrap<testClass> a;
a(&testClass::f,13,'a');
}
It's working (gcc, c++0x). But when I replace the 6,7th line with the following (to actually wrap the result)
wrap<L> operator() (L(T::*f)(R...),R...r){
return wrap<L>(a.f(r...));
The compiler just sais: creating pointer to member function of non-class type "int".
How can I fix this? Is there any better to do this? Inheritence is one way but since we might have variable instance in one wrap, I think it's not useful.
EDIT
Here's my test class
struct testClass{
int f(int a,char b){
return a+b;
}
};
The reason why I'm using wrap L instead of wrap T is that the return type might not always be T.
You can try something like this:
#include <iostream>
#include <type_traits>
template<class T, bool = false>
struct wrap{
template <typename... Args>
wrap(Args&&... args) : a{std::forward<Args>(args)...} {};
template<class L, class...R>
wrap<L,std::is_fundamental<L>::value> operator() (L(T::*f)(R...),R...r){
return wrap<L,std::is_fundamental<L>::value > {(a.*f)(r...)};
}
T a;
};
template<class T>
struct wrap <T,true>{
template <typename... Args>
wrap(Args&&... args) : a{std::forward<Args>(args)...} {}
template<class L, class...R>
wrap<L,std::is_fundamental<L>::value> operator() (L(*f)(T a, R...), R...r){
return wrap<L,std::is_fundamental<L>::value > {f(a, r...)};
}
T a;
};
class testClass {
int m;
public:
testClass(int _m) : m{_m}{}
int multiAdd(int x, char y) {
m += x + y;
return m;
}
};
int add(int a, char b)
{
return a+b;
}
int main(){
wrap<testClass> a{0};
std::cout << a(&testClass::multiAdd,0,'d')(add,'a').a<<std::endl;
wrap<int, true> b{3};
std::cout << b(add,'a').a<<std::endl;
}
cpp.sh/6icg
It seems the error is in your testclass definition. Please check the below example.
Also, wrap in the operator() can be returned as reference. I don't see any need to create temporaries to be used for () chaining.
template<class T>
struct wrap{
template <typename... Args>
wrap(Args&&... args) : a{std::forward<Args>(args)...} {};
template<class L, class...R>
wrap<T>& operator() (L(T::*f)(R...),R...r){
a.f(r...);
return *this; //returning reference to current wrap object.
}
T a;
};
A test class to accumulate numbers.
class testClass {
int m;
public:
testClass(int _m) : m{_m}{}
int f(int x) {
m += x;
std::cout << ' ' << m;
return m;
}
};
An usage example:
int main(){
wrap<testClass> a{0};
a(&testClass::f,13)(&testClass::f, 11)(&testClass::f,3)(&testClass::f, 21);
}
Output of sum accumulated at each step:
13 24 27 48
I would like to have a general templated function declaration for which I do not know (already) the return type, similar to:
**template <class T> auto getIds() noexcept -> std::vector<Any>;**
The function could then be specialized with several input types, and a return type based on it:
template <> auto getIds<MyClass>() noexcept -> std::vector<decltype(MyClass::id)>
{
// implementation here.
}
And finally call it without to set the return:
auto val = getIds<MyClass>();
Is that possible? How?
Notes:
What I want to avoid is to have to set manually the Id type in the call function:
auto val = getIds<MyClass, decltype(MyClass::id)>(); // Ugly
I also discard any (non based on template) solution like extending all types from a RootMyClass. Is not that these solutions are bad, but they miss the point of this question.
Trying to be a bit clearer:
If I wrote
class MyClass { public: int id1=4;};
template <class T, class Id> auto getIds() -> Id;
template <> auto getIds<MyClass, decltype(MyClass::id1)>() -> decltype(MyClass::id1)
{
return 1;
}
auto main() -> int
{
getIds<MyClass>(); // Do not compile
getIds<MyClass, decltype(MyClass::id1)>(); // Compile but ugly
}
I would like the return type to be implicit, but I did not found a way to achieve that with specializations:
template <class T> getIds() noexcept -> WHICH TYPE?;
You cannot change the return type in a specialization, unfortunately. What you can do is change the return type in different overloads. Obviously. Furthermore, function template specializations are much more complicated than function overloads anyway, so let's do that.
Introduce an empty type wrapper, say:
template <typename T> struct wrapper { };
And forward the default implementation to that (I'm assuming C++14 here, otherwise you could wrap that in decltype() with a trailing return):
template <typename T>
auto getIds() { return getIds(wrapper<T>{}); }
Declare the generic version as:
template <typename T>
void getIds(wrapper<T> );
Don't define it. Then, anytime somebody tries to do:
auto ids = getIds<X>();
If there is no overload, that will simply fail to compile as you cannot assign from void. Then, you can overload as you see fit:
std::vector<decltype(MyClass::id)> getIds(wrapper<MyClass> )
{ ... }
FINAL EXAMPLE:
#include <iostream>
#include <vector>
template <typename T> struct wrapper { };
template <typename T>
auto getIds() -> decltype(getIds(wrapper<T>{}))
{
return getIds(wrapper<T>{});
}
template <typename T>
void getIds(wrapper<T> ) { }
struct MyClass {
int id;
};
std::vector<decltype(MyClass::id)> getIds(wrapper<MyClass> )
{
return {1, 2, 3};
}
int main()
{
for (auto id : getIds<MyClass>()) {
std::cout << id << " ";
}
}
This is actually very similar to Haskell typeclasses, and, surprisingly, works. For real usage I would use functors to allow partial specializations, though.
#include <iostream>
template<typename T>
decltype(T::x) getX(T const& t) { return; }
class A { public: int x; A(int x):x(x){} };
template<> int getX<A>(A const& a) {
return a.x;
}
class B { public: std::string x; B(std::string x):x(std::move(x)){} };
template<> std::string getX<B>(B const& b) {
return b.x;
}
int main() {
A a(42);
B b("43");
std::cout << getX(a) << std::endl;
std::cout << getX(b) << std::endl;
}
As you can see, each specialization has to (can?) provide the return type explicitly. decltype(A::x) (and B::x), respectively) could be used instead if you so prefer.
To make it even more Haskell-ish, you could expect a type tag in the type itself (basically a type family):
template<typename T>
typename T::TypeOfX getX(T const& t) { return; }
And consequently:
class A {
using TypeOfX = int;
TypeOfX someComplexLogicToGetX();
};
Both solutions to the type being instantiated for the actual type, except one gets it from a type of a field, and the other from a direct "type variable".