typelist-like (?) template class - c++

I'm trying to achieve following: create template class which uses its template arguments to create instance of template type and use it somewhere in the, for example constructor. Consider following example:
template <typename T>
class foo
{
public:
explicit foo(const T& data) : m_data(data) {}
T m_data;
};
template <typename T01, typename T02>
class bar
{
public:
explicit bar(int data) : m_storage(T01(data), T02(data)) {}
void print() { boost::fusion::for_each(m_storage, printer()); }
private:
boost::fusion::vector<T01, T02> m_storage;
};
and usage:
bar<foo<int>, foo<int>> b(5);
b.print();
but what if I want flexibility in the bar class and I want number of these T01, T02 classes varying?
example:
bar<foo<int>, foo<int>> b(5);
b.print();
bar<foo<int>, foo<int>>, foo<int>> c(6);
c.print();
Something like using argument pack maybe?
EDIT001:
Final working version on coliru.

You are looking for variadic template (available since C++11)
template <typename ... Ts>
class bar
{
public:
explicit bar(int data) : m_storage(Ts(data)...) {}
void print() { boost::fusion::for_each(m_storage, printer()); }
private:
boost::fusion::vector<Ts...> m_storage;
};

Related

How to efficiently initialize a std::variant data member in a class template

Consider the following class template, that can hold either a value of type T or an instance of some ErrorInfo class, using a std::variant data member:
template <typename T>
class ValueOrError
{
private:
std::variant<T, ErrorInfo> m_var;
};
How can I efficiently initialize the variant T alternative?
I can initialize it with a constructor like this:
template <typename T>
class ValueOrError
{
public:
explicit ValueOrError(const T& val)
: m_var{val}
{
}
…
};
But what syntax/coding technique can I use to enable move semantics optimization during initialization?
If I define a constructor taking a T&&, should I std::move or std::forward the parameter into the m_var?
template <typename T>
class ValueOrError
{
public:
// Efficient initialization with move semantics
explicit ValueOrError(T&& val)
: m_var{ /* ?? */ }
{
}
…
};
Note on interactions with ErrorInfo constructor overload
The ValueOrError template should also have a constructor overload that takes an ErrorInfo and initializes the variant member accordingly:
template <typename T>
class ValueOrError
{
public:
// Initialize with error code instead of T
explicit ValueOrError(const ErrorInfo& error)
: m_var{error}
{
}
…
};
It’s important that the generic T constructor overload interacts properly with the specific ErrorInfo overload.
ErrorInfo is a tiny class that wraps an error code (e.g. a simple integer), and can be constructed from such error code:
class ErrorInfo
{
public:
explicit ErrorInfo(int errorCode)
: m_errorCode{errorCode}
{
}
int ErrorCode() const
{
return m_errorCode;
}
// … other convenient methods
// (e.g. get an error message, etc.)
private:
int m_errorCode;
};
A C++20 version using perfect forwarding:
#include <concepts> // std::constructible_from
template <class T>
class ValueOrError {
public:
explicit ValueOrError(const ErrorInfo& error) : m_var{error} {}
template<class... Args>
requires std::constructible_from<T, Args...>
explicit ValueOrError(Args&&... val) :
m_var(std::in_place_type<T>, std::forward<Args>(val)...)
{}
private:
std::variant<T, ErrorInfo> m_var;
};
A C++17 version, also using perfect forwarding, could look like this:
#include <type_traits> // std::is_constructible_v, std::enable_if_t
template <class T>
class ValueOrError {
public:
explicit ValueOrError(const ErrorInfo& error) : m_var{error} {}
template<class... Args,
std::enable_if_t<std::is_constructible_v<T, Args...>, int> = 0>
explicit ValueOrError(Args&&... val)
: m_var(std::in_place_type<T>, std::forward<Args>(val)...) {}
private:
std::variant<T, ErrorInfo> m_var;
};
Example usages:
class foo { // A non default constructible needing 3 constructor args
public:
foo(double X, double Y, double Z) : x(X), y(Y), z(Z) {}
private:
double x, y, z;
};
int main() {
ValueOrError<foo> voe1(1., 2., 3.); // supply all three arguments
// use the string constructor taking a `const char*`:
ValueOrError<std::string> voe2("Hello");
std::string y = "world";
// use the string constructor taking two iterators:
ValueOrError<std::string> voe3(y.begin(), y.end());
}
I would do this this way in C++17 (using "perfect forwarding" + SFINAE):
template <typename T>
class ValueOrError
{
public:
template<typename U>
explicit ValueOrError(U&& val, std::enable_if_t<std::is_constructible_v<T, U>>* = nullptr)
{
m_var.template emplace<T>(std::forward<U>(val));
}
private:
std::variant<T, ErrorInfo> m_var = ErrorInfo{0};
};
Question is how this interact with constructors were error should be used?
Or initialization list version:
template <typename T>
class ValueOrError {
public:
template <typename U>
explicit ValueOrError(U&& val, std::enable_if_t<std::is_constructible_v<T, U>>* = nullptr)
: m_var { std::in_place_type<T>, std::forward<U>(val) }
{
}
private:
std::variant<T, ErrorInfo> m_var;
};
I have doubts if version with multiple arguments to construct T should be implemented. It is possible, but IMO will make code harder to read.
https://godbolt.org/z/scxacMn3W

Template arguments in constructor of non-template class

I want to have a constructor of a non-template class which is templated by a type. Can anyone help here?
class A
{
public:
static int GetId(){ return 5;}
};
class B
{
public:
B(int id){ _id = id;}
template<typename T>
B() {_id = T::GetId();}
template<typename T>
static B* newB() {return new B(T::GetId());}
private:
int _id;
};
void doSome()
{
B* p1 = B::newB<A>(); //works
B* p2 = new B<A>(); //doesn't compile -- ">>B<< is no template"
}
All template parameters of a constructor template must be deducible (or have default arguments), because there is no syntax for explicitly passing template arguments to a constructor (as you've learned).
There are several possible ways around this:
Provide a constructor-like function template. You're already doing this with newB, there's just no need to force dynamic allocation:
template <class T>
B create() { return B(T::GetId()); }
Provide a tag type and parameterise the consturctor by that:
template <class T>
struct Tag {};
class B
{
public:
template <class T>
B(Tag<T>) : _id(T::GetId()) {}
};
//usage:
B b(Tag<A>());
You cannot explicitly specify the constructor template parameter. It must be deductible.
One solution is to use a helper parameter:
template <class T>
struct Type_holder { using Type = T; };
class B {
public:
B(int id) : id{id} {}
template<typename T>
B(Type_holder<T>) : id{T::GetId()} {}
private:
int id;
};
auto foo()
{
B b{Type_holder<A>{}};
}
Also, please use constructor initialization lists. And careful with those dynamic allocations. Don't use it if it's not needed. And when it's needed use smart pointers.

How to forward std::initializer_list<T>?

I am trying to forward a std::initializer_list but
no known conversion from 'std::initializer_list<A>' to 'std::initializer_list<B>'
Here is the test code
#include <iostream>
class B {
};
class A: public B {
};
class not_working {
private:
void fun(std::initializer_list<B> p) {
}
public:
template<typename T>
not_working(std::initializer_list<T> args) {
fun(args);
}
};
class working {
private:
void fun(std::initializer_list<B> p) {
}
public:
working(std::initializer_list<B> args) {
fun(args);
}
};
int main(){
working{A{}, A{}};
//not_working{A{}, A{}};
}
How can I forward the std::initializer_list
without explicit casting not_working{(B)A{}, (B)A{}}; ?
Why is this a problem for me ?
I have a proxy-class that forwards the constructor-parameters to a class.
Something like this:
template<typename T>
class proxy {
T real;
template<typename S> proxy(std::initializer_list<S> p): real(p) {}
template<typename S...> proxy(S ... p): real(p ...) {}
};
You cant, and the reason is the same as why you also could not cast a std::vector<A> to a std::vector<B>. Containers of different types are completely unrelated.
The only way to "change" the type of a container is to construct a new container of the new type (eg, std::vector<B>(a.begin(), a.end()) -- but beware of slicing!).
Posting answer from comments of question to increase visibility of the solution:
Standard solution is to use std::forward. This fails forwarding initializer lists.
template<typename T>
class proxy {
T real;
public:
template<typename ... S> proxy(S ... p): real{std::forward<S>(args)...} {}
};
Using std::move, also works with std::initializer_list (provided by #dyp) :
template<typename T>
class proxy {
T real;
public:
template<typename ... S> proxy(S ... p): real{std::move(p) ...} {}
};

How to circumvent virtual template member functions?

I have a template class Field<T> which inherits from a non-template abstract base class AbstractField to be able to store all different kinds of Field<T> * types in a std::vector<AbstractField *>. My setup is as follows:
#include <vector>
class AbstractField
{
public:
virtual ~AbstractField() {};
// Something similar to: template<class T> T getValue() const; ?
};
template<class T>
class Field : public AbstractField
{
private:
T d_;
public:
Field(T d) : d_(d) {}
T getValue() const { return d_; }
};
int main()
{
AbstractField *f = new Field<double>(0.1);
// How to call: f->getValue(); ?
return 0;
}
I was wondering what would be the most natural way to call f->getValue() since I can't use a virtual template member function in the AbstractField class. As far as possible, I would prefer not using boost. Any hints are welcome!
EDIT:
Corrected std::vector<Field<T> > to std::vector<AbstractField *>. Sorry for the confusion.
Maybe this:
template <typename> struct Field;
struct AbstractField
{
virtual ~AbstractField() {}
template <typename T> T getValue()
{
return dynamic_cast<Field<T>&>(*this)->get();
}
};
template <typename T> struct Field : AbstractField
{
T & get();
// ...
};

Refactoring c++ template class based on template type

Given class Foo
template <typename T>
class Foo
{
public:
...other methods..
void bar()
{
...
m_impl.doSomething();
...
}
void fun()
{
...
m_impl.doSomethingElse();
...
}
void fubar()
{
...
}
private:
T m_impl;
};
I wanted to cater for situations where T is a boost::shared_ptr.
In this case the only change to class Foo is that it should invoke
m_impl->doSomething();
instead of
m_impl.doSomething();
I ended up defining FooPtr in the same header
template <typename T>
class FooPtr
{
public:
...other methods..
void bar()
{
...
m_pImpl->doSomething();
...
}
void fun()
{
...
m_pImpl->doSomethingElse();
...
}
void fubar()
{
...
}
private:
boost::shared_ptr<T> m_pImpl;
};
Now while the approach works for all classes that I want to use with Foo,
the problem is that I have a lot of duplicate code lying around and any changes
I make to Foo, I also have to make to FooPtr.
How can I refactor the code? E.g. Is there any way that I can determine at compile time if T is of type boost::shared_ptr, and then specialise just the bar and fun methods to invoke the -> operator?
Edit:
Thanks for all the answers so far! I just need some time to work through them all and see which solution is the best fit for our software.
Edit 2:
#Matthieu: This is the test code I was using
class FooImpl
{
public:
void doIt()
{
cout << "A" << std::endl;
}
};
int _tmain(int argc, _TCHAR* argv[])
{
Foo<FooImpl> foo;
foo.doSomething();
return 0;
}
Sylvain wrote a DRY solution, but I don't like abusing inheritance.
Using a wrapper class to uniformize the interface is easy, especially since pointer semantics work so well!
namespace details {
template <typename T>
struct FooDeducer {
typedef boost::optional<T> type;
};
template <typename T>
struct FooDeducer< T* > {
typedef T* type;
};
template <typename T>
struct FooDeducer< boost::shared_ptr<T> > {
typedef boost::shared_ptr<T> type;
};
} // namespace details
template <typename T>
class Foo {
public:
// methods
void doSomething() { impl->doIt(); }
private:
typedef typename details::FooDeducer<T>::type Type;
Type impl;
};
Here, relying on boost::optional which provides the OptionalPointee semantics, we nearly get the same behavior than pointers.
One point I'd like to emphasize though, is the difference in the copying behavior. boost::optional provides deep copy.
class A
{
public:
void doSomething() {}
};
template <typename T>
class Foo
{
public:
void bar()
{
Impl(m_impl).doSomething();
}
private:
template<typename P>
P& Impl(P* e)
{
return *e;
}
template<typename P>
P& Impl(std::shared_ptr<P> e)
{
return *e;
}
template<typename P>
P& Impl(P& e)
{
return e;
}
T m_impl;
};
You can write a caller class template, whose job is to call the function, either using syntax obj.f() or obj->f(), based on the type of obj.
Here is a small example that demonstrates this approach:
template<typename T>
struct caller
{
static void call(T &obj) { obj.f(); } //uses obj.f() syntax
};
template<typename T>
struct caller<T*>
{
static void call(T* obj) { obj->f(); } //uses obj->f() syntax
};
And this caller class template is used by this sample class:
template<typename T>
struct X
{
T obj;
X(T o) : obj(o) {}
void h()
{
caller<T>::call(obj); //this selects the appropriate syntax!
}
};
See this online running demo at ideone : http://www.ideone.com/H18n7
--
EDIT:
This is even more generic. Here you can even pass the function which you want to call in caller. Now caller is not hard-coded with the function to be called!
http://www.ideone.com/83H52
I really question whether you should be using a template here at all. Your template parameter has a very clear interface and therefore looks like you should just use an abstract base class.
Do you really need to have an instance? If you do need to change the way the object is represented, this should be done as a separate exercise and not part of the template that uses it.
You can introduce another intermediate template class, something like that:
template < typename T >
class FooBase
{
private:
T m_impl;
protected:
T& impl() { return m_impl; }
};
template < typename T >
class FooBase< boost::shared_ptr< T > >
{
private:
boost::shared_ptr< T > m_impl;
protected:
T& impl() { return *(m_impl.operator ->()); }
};
template < typename T >
class Foo : protected FooBase< T >
{
public:
void bar()
{
impl().DoSomething();
}
};
Now, you only have to code the Foo class only once. And you can specialize it for other smart pointers type by doing partial specialization on FooBase.
Edit: You can also use composition instead of having an inheritance relationship between Foo and FooBase (in which case, I'd probably rename it to FooHelper or something like that).
template < typename T >
class FooHelper
{
private:
T m_impl;
public:
T& impl() { return m_impl; }
};
template < typename T >
class FooHelper< boost::shared_ptr< T > >
{
private:
boost::shared_ptr< T > m_impl;
public:
T& impl() { return *(m_impl.operator ->()); }
};
template < typename T >
class Foo
{
private:
FooHelper< T > m_helper;
public:
void bar()
{
m_helper.impl().DoSomething();
}
};
You can use partial specialization.
template <typename T>
class Foo
{
public:
//...
};
template<typename T> class Foo<boost::shared_ptr<T>> {
//... implement specialization here
};