Declare new function inside a class using a template - c++

I'm still learning about templates. I'm not sure whether you can declare/(automatically define) a function inside a class (method) using a template. That is, I have a function template defined like this, for example:
template<typename T>
T getT() {
T result;
return result;
}
And a class, where I want the "new function" to be created, based on the template, like this:
class World{
public:
World();
~World();
getT<int>; //"Magically" create new function from the template (return type 'int')
}
What I actually want is to have only a method with the specific given type in World. That means when I want to "magically" create a method based on the template, I want to sort of copy-paste the template function into the class but with the given type.
For example:
class World{
public:
World();
~World();
//The magically created function with T equal to int
int getT(){
int result;
return result;
}
}
Then of course I expect to be able to call the function:
int main(){
World world; //Create world object
world.getT<int>; //Call the function
return 0;
}
Even though here I say I would call it with getT<int>, it could be only getT() (if it is a perfect copy-paste of the template function).

Be carfull
template<typename T>
T& getT() {
T result;
return result;
}
Will return a reference to a temporary. Please do
template<typename T>
T getT() {
T result;
return result;
}
without "&"
And if it's just for get a specific member, you can use std::tuple.
https://en.cppreference.com/w/cpp/utility/tuple/get

getT<int>; //"Magically" create new function from the template (return type 'int')
I don't think that will work.
It appears as though you would like to be able to use templates like macro expansion. Unfortunately, they are very different things and templates don't work like macro expansion.
However, you can use something like the following:
template<typename T>
struct GetHelper
{
T get()
{
return T{};
}
};
class World : private GetHelper<int>,
private GetHelper<double>
{
public:
World() {}
~World() {}
template <typename T>
get()
{
return static_cast<GetHelper<T>*>(this)->get();
}
};
Now you can use:
World w;
int a = w.get<int>();
double b = w.get<double>();
You may also hide GetHelper as a private type of World as:
class World
{
private:
template<typename T>
struct GetHelper
{
T get()
{
return T{};
}
};
struct Data : GetHelper<int>,
GetHelper<double>{};
Data data;
public:
World() {}
~World() {}
template <typename T>
get()
{
return static_cast<GetHelper<T>*>(&data)->get();
}
};

Related

Forward function calls to underlying data in a wrapper template

I'm writing a template wrapper, something like this
template<class T>
class Wrapper{
public:
Wrapper(T data);
~Wrapper();
void doSomeWrapperWork();
private:
T data;
};
If I want to access the wrapped data, I can obviously add a getter function that returns a reference to the data. I was wondering however if there is anyway, with some template magic, to call directly on the wrapper functions of the underlying wrapped data. In other words, if I have a class TestObject with a public function void foo(), I would like to be able to call it in this way:
Wrapper<TestObject> myWrapper;
myWrapper.foo();
instead of:
myWrapper.getData().foo();
without knowing a priori that such a function exists. Is this possible?
Not quite, until C++ gets reflection we can't easily write wrapper classes without a lot of boilerplate macros
but
You can add an implicit conversion of your wrapper class to T:
template<class T>
class Wrapper{
public:
Wrapper(T data_) : data(data_) {}
operator const T&() const
{
return data;
}
private:
T data;
};
And now your class is convertible to T, so we can call a method on T, with a little work:
usage:
struct Foo
{
constexpr int bar() const
{
return 42;
}
};
int main()
{
constexpr Foo f;
Wrapper<Foo> my_wrapper(f);
static_assert(static_cast<const Foo&>(my_wrapper).bar() == 42);
}
Demo
If you want to avoid the casting yourself, you can write a free function that will call your function, so that implicit conversion may take over:
int call_bar(const Foo& f)
{
return f.bar();
}
Usage:
Foo f;
Wrapper<Foo> my_wrapper(f);
std::cout << call_bar(my_wrapper); // 42
Demo2
I kind of like this approach as all it requires is that we add a free function for each wrapped function we want instead of having to manually do a bunch of casting.
Yes, try something like
#include <iostream>
struct TestObject{
void foo() { std::cout << "TestObject" << std::endl;}
};
template <class T>
struct Wrapper : public T{
Wrapper() {}
void doSomeWrapperWork() {}
};
int main() {
Wrapper<TestObject> wrapper;
wrapper.foo();
}
This allows you to add more functionality as need while still allowing the wrapper to be used as a class T.
This is inspired by the decorator design pattern.

CRTP and lifetime extension

My question is how to make lifetime extension work with CRTP. For example, the following code is perfectly valid:
struct A {
const int& ref;
};
struct B {
const A& a;
};
int main() {
B b{{123}};
return b.a.ref;
}
Its CRTPed version is not:
template <class DerivedT>
class Gettable {
public:
int Get() const {
return static_cast<const DerivedT*>(this)->GetImpl();
}
};
class A : public Gettable<A> {
friend class Gettable<A>;
public:
A(int r) : ref{r}{}
private:
int GetImpl() const {
return ref;
}
const int& ref;
};
template <class T>
class B {
public:
B(const Gettable<T>& gettable) : get_{gettable}{}
int DifferentGet() const {
return get_.Get();
}
private:
const Gettable<T>& get_;
};
int main() {
B b{A{123}};
return b.DifferentGet();
}
The problem is that the original A and its Gettable<A> subobject only exist till the the of B constructor.
I have two questions:
1) Why? It is in no way different from the first case of structs, every lifetime is known at compile time, so I believe that compiler should be able to extend lifetime of all temporaries.
2) Is there any good way to overcome this issue?
1) Why?
Because there is a function involved - the constructor. The temporary is not bound directly to the member, but rather it is bound directly to the argument of the function - whose lifetime extends until the end of the function, which does not extend beyond the full expression that invoces the function.
It is in no way different from the first case of structs
It is different. There is no constructor involved in aggregate initialisation. In that case, the compiler knows the lifetime of the member, and it knows that the member is initialised with the temporary. The lifetime extension rule applies.
so I believe that compiler should be able to extend lifetime of all temporaries.
Consider following example:
struct foo {};
struct bar {
bar(const foo& farg);
const foo& fmem;
};
bar b({});
Should the lifetime of the temporary to extend for the lifetime of b? The standard says, that it doesn't. You appear to be arguing that it should.
Consider following possible implementations of the constructor:
bar::bar(const foo& farg) : fmem{farg} {} // 1
foo fanother;
bar::bar(const foo& farg) : fmem{fanother} {} // 2
If the implementation happens to be 1, then you guessed right, the life time extension is needed. If implementation is 2, then we are unnecessarily extending a temporary that is not referred to anymore.
The language designers chose to not extend such temporary, probably so that life times of temporaries don't get extended unnecessarily. As a consequence, implementation 1 is wrong, as well as your CRTP example.
Concisely: The compiler can only extend the lifetime of a temporary until the lifetime of the reference to which the temporary is bound directly. The compiler cannot know what will be done with the reference within the function. It cannot know that an argument has something to do with a member. Those are only known when the constructor is compiled - not when a call to the constructor is compiled.
2) Is there any good way to overcome this issue?
Use either int* or std::reference_wrapper<int> as the constructor argument. Former is more concise, but latter has convenient property of not having a null representation. These should make it harder to accidentally bind a dangling reference. Regardless, document carefully that the referred object must still be valid when Get is called.
I believe that the most general solution is something like this. This way it works even for multilevel inheritance.
#include <iostream>
#include <utility>
#include <type_traits>
struct NullType {};
// Helper class for casting
template <class Derived>
class DerivedCaster {
protected:
Derived* GetDerived() {
return static_cast<Derived*>(this);
}
const Derived* GetDerived() const {
return static_cast<const Derived*>(this);
}
};
// Matches the predicate against the types and remembers the first
// satisfying argument
template <template <class T> class Predicate, class... Args>
struct FindFirstMatching {
using Type = ... ; // default NullType
static const bool has_match = ... ;
};
// Structure which gets the deepest class from CRTP inheritance chain
// by looking at the instantiated parent class template
template<typename T>
struct GetDeepest
{
using Type = T;
};
template<template<class...> class DT, class... T>
struct GetDeepest<DT<T...>>
{
template <class CLS>
struct Predicate {
static const bool value = std::is_base_of<DT<T...>, CLS>::value;
};
static const bool HasCRTPDerived = FindFirstMatching<Predicate, T...>::has_match;
using DerivedT = typename FindFirstMatching<Predicate, T...>::Type;
using Type = std::conditional_t<HasCRTPDerived, typename GetDeepest<DerivedT>::Type, DT<T...>>;
};
// First abstract class
template <class DerivedT>
class Gettable : public DerivedCaster<DerivedT> {
public:
int Get() const {
return DerivedCaster<DerivedT>::GetDerived()->GetImpl();
}
};
// Second abstract class
template <class DerivedT>
class Incrementable : public DerivedCaster<DerivedT>,
public Gettable<Incrementable<DerivedT>> {
friend class Gettable<Incrementable<DerivedT>>;
public:
int Increment() const {
return ++(this->Get());
}
private:
int GetImpl() const {
return DerivedCaster<DerivedT>::GetDerived()->GetImpl() + 100;
}
};
// non-abstract class
class A : public Incrementable<A> {
friend class Incrementable<A>;
public:
A(int r) : ref_{r}{}
private:
int GetImpl() const {
return ref_;
}
int ref_;
};
// Helper to get the copy of the underlying non-abstract class
template <class T>
auto GetDeepestLevelCopy(const T& arg) {
return static_cast<const typename GetDeepest<T>::Type&>(arg);
}
// Some other class which wants a copy
template <class T>
class B {
public:
B(const Gettable<T>& gettable) : get_{GetDeepestLevelCopy(gettable)}{}
int DifferentGet() const {
return get_.Get();
}
private:
typename GetDeepest<Gettable<T>>::Type get_;
};
int main() {
static_assert(std::is_same_v<GetDeepest<Gettable<Incrementable<A>>>::Type, A>);
static_assert(std::is_same_v<decltype(GetDeepestLevelCopy(std::declval<Gettable<Incrementable<A>>>())), A>);
B b{A{123}};
std::cout << b.DifferentGet() << "\n";
// prints 223
return 0;
}
This looks monstrous, but I don't know whether there is a better solution.

Way to call a static method of a class template without specifying an instantiation?

Is there any way to define a static method in a class template which can be then be called without specifying the instantiation?
I think this could be useful in cases where you have some auxiliary static function, which logically belongs in a class (which happens to be a template one), but doesn't depend on the template parameter.
I don't mind either:
Having the same static method (including address and all) for all
instantiations, or
Having a separate static method for each instantiation, but be able to call the static method without
specifying an instantiation where I call the method (some default
would be called).
e.g.
template<typename T> class C {
public:
static int func() { return 0; }
};
int main()
{
// This works.
return C<int>::func();
// These don't work.
// return C<>::func();
// return C::func();
}
The simplest solution is probably to have the static function belong in a base class, and then the template derives from the base:
struct CBase {
static int func() { return 0; }
};
template<typename T> class C : public CBase {
public:
};
int main()
{
// This works.
return C<int>::func();
// This will work too:
return CBase::func();
}
You can use inheritance which will also remove the duplication of any non static functions ( that also don't care about the template type ) in your binary, i.e:
class A {
public:
static int func() { return 0; }
};
template<typename T>
class B : A {
};
If you want to get C or C<> to work you can either rely on a base non-template class that contains the given function or use template specializations as it follows:
template<typename...>
struct C;
template<>
struct C<> {
static int func() { return 0; }
};
template<typename T>
struct C<T>: C<> {
// all the other things around...
};
int main() {
C<int>::func();
C<>::func();
}
For you don't provide a definition for the primary template, accepted specializations are:
C<> that contains only the given function
C<T> that accepts only a parameter as it was in the original example
See it on wandbox.
If you can't use variadic templates, you can still do something similar with a custom type.
As an example:
struct func_only {};
template<typename T = func_only>
struct C;
template<>
struct C<func_only> {
static int func() { return 0; }
};
template<typename T>
struct C: C<func_only> {
// all the other things around...
};
int main() {
C<int>::func();
C<>::func();
}
That being said, make it a free function looks to me as the best solution anyway.
How would that work? You typically depend on the type in your static functions too.
template<typename T> class C {
public:
static int func() { return sizeof(T); }
};
If they do not depend on it, you should probably make them free functions, or static members of a base class of this class.

C++ templating syntax - allocate type with pointer

How can I do memory allocation like this:
template <class T>
class A
{
T Generate()
{
return new T(); // Error
}
};
A<B *> a;
B * pI = A.Generate();
Or can you only ever define something as:
A<B> a;
If I understood you correctly you wish to have specialization of A for pointer types. Try something like:
#include <cstdio>
template <class T>
class A
{
public:
T *Generate()
{
printf("A\n");
return new T; // Error
}
};
template <class T>
class A<T*> {
public:
T *Generate() {
printf("Specialization of A\n");
return new T;
}
};
class B {
};
int main() {
A<B *> a;
B * pI = a.Generate();
}
Edit:
To "override" only a part of the functionality:
template <class T>
class Generator
{
public:
T *Generate()
{
printf("Generator\n");
return new T; // Error
}
};
template <class T>
class Generator<T*> {
public:
T *Generate() {
printf("Specialization of Generator\n");
return new T;
}
};
template <class T>
class A: public Generator<T>
{
public:
// does some other stuff
};
You have a bunch of issues with your code:
A.Generate() should be a.Generate() as Generate is a member function.
new T() returns T*, so your Generate function should look like:
T* Generate()
{
return new T();
}
This should also be reflected in your usage:
A<B *> a;
B ** pI = a.Generate(); //generator for B* returns B**
new will return a pointer so you need the signature
T* Generate()
{
return new T();
}
This function must also be public if you'd like to call it outside the class.
How can I do memory allocation like this
By fixing the syntax and semantic errors.
Return type of Generate is T, yet you return T*. You probably want to change the return type to T*. Accordingly, you must assign the returned type to a T* variable. Since your T is B*, that variable must have the type B**.
You try to call a non-static member of A without an instance. Call the member using the instance instead. Also, that member is private. Make it public.
When you've fixed the code, you'll see that it does memory allocation successfully.
Or can you only ever define something as:
A<B> a;
No, there are many more ways to define something.

Template function having its caller's context?

Consider the following code snippet.
template <T>
MyPtr<T> CreateObject()
{
// Do something here first...
// return our new object
return MyPtr<T>(new T());
}
class Foo
{
private:
Foo() { }
public:
static MyPtr<Foo> GetNewInstance()
{
// ERROR: Foo is private...
return CreateObject<Foo>();
}
};
class Bar
{
public:
Bar() { }
};
int main()
{
MyPtr<Bar> bar = CreateObject<Bar>();
return 0;
}
Without resorting to macro for CreateObject (I like the syntax of MyPtr<type> obj = CreateObject<type>(params)), is there a way to make the function CreateObject share the same context as the caller function, thus able to access private Foo c'tor? 'friend' is not what I'm looking for as it would mean anyone calling CreateObject would have access to private Foo c'tor, which is not what I want. Overloading the new operator wouldn't work either as it is imperative that a MyPtr is returned instead of just T* (by assigning T* to MyPtr assigns a type to the object that is required somewhere else).
I guess what I'm looking for is something in between a macro and a template function (syntax of a template function but gets expanded fully like a macro). It would be quite useful to have this feature in this particular case.
Well, you could do that with the passkey pattern:
template<class T, class PassKey>
MyPtr<T> CreateObject(PassKey const& key)
{
return new T(key);
}
class FooKey{
private:
FooKey(){} // private ctor
FooKey(const FooKey&); // undefined private copy ctor
friend class Foo;
};
class Foo{
public:
// public ctor
Foo(FooKey const&){}
static MyPtr<Foo> GetNewInstance()
{
return CreateObject<Foo>(FooKey());
}
};
Example at Ideone.
With C++0x, this can be done much easier than creating a new Key struct every time, since template parameters are now allowed to be friends:
template<class T>
struct PassKey{
private:
PassKey(){}
PassKey(const PassKey<T>&);
friend T;
};
This is basically the same as attempting to use make_shared with a private constructor.
The only way to allow this is with friend. You're pretty much stuck in this case I'm afraid.
I am not sure as to what you are trying to achieve. The simplification to post the problem here has taken away the actual need for the whole thing. So I will just assume that you know what you are doing, and that you really need this (and I suggest that you rethink whether you do need it, as I don't see a point...)
At any rate, you can solve the problem by passing a creator callback to the CreateObject template:
template <typename T, typename Creator>
MyPtr<T> CreateObject( Creator creator )
{
// Do something here first...
return MyPtr<T>(creator());
}
class Foo
{
private:
Foo() {}
static Foo* create() { return new Foo(); }
public:
static MyPtr<Foo> GetNewInstance() {
return CreateObject<Foo>( &Foo:create );
}
// ...
};
The actual issue though, is what does Do something here first actually does that forces you into this complex creation patterns. The fact that it has to be executed before the creation of the new object seems to indicate that there are hidden dependencies not shown in the code, and that usually end up in maintenance nightmares, where someone down the line reorders some code, or adds a new constructor and everything seems to fall apart. Revisit your design and consider whether those dependencies can be simplified or made explicit.
Since you are newing up the object in the very end it really doesn't relate to your CreateObject function. So Change the function prototype to:
template <typename T>
MyPtr<T> CreateObject(T* const p)
{
//...
return MyPtr<T>(p);
}
Usage:
static MyPtr<Foo> GetNewInstance()
{
return CreateObject(new Foo());
}
is there a way to make the function CreateObject share the same context as the caller function
Yes, pass the context you need as an argument (either as an argument to the template, or as an argument to the function).
In practice, move the new T call to a separate function (or struct template, as I chose to do here), like this:
// Dummy representation of your pointer type
template <typename T>
struct MyPtr
{
MyPtr( T *p ) { }
};
// Default constructor template; may be specialized to not use "new" or so.
template <typename T>
struct Constructor
{
static T *invoke() { return new T; }
};
// Needs to be a struct (or class) so 'C' can have a default value
template <typename T, typename C = Constructor<T> >
struct CreateObject
{
MyPtr<T> operator()() {
return MyPtr<T>( C::invoke() );
}
};
class Foo
{
private:
friend struct Constructor<Foo>;
Foo() { }
public:
static MyPtr<Foo> GetNewInstance()
{
return CreateObject<Foo>()();
}
};
If you want to handle different constructor signatures (read: if not all types T have the same constructor signature), you could also choose to not pass the Constructor as a template to the CreateObject struct, but instead use a function argument. That way, you could 'load' a Constructor like this:
// ...
static MyPtr<Foo> GetNewInstance()
{
Constructor<Foo> c( arg1, arg2, arg3 );
return CreateObject<Foo>( c );
}