Setting data for member in class fails with template error - c++

I have 2 classes like this
template <class T>
class CData
{
std::vector<T> data;
public:
void SetData(std::vector<T> vt){data.assign(vt.begin(),vt.end());}
};
template <class... T>
class CDataHolder
{
std::tuple<Data<T>...> m_data;
//... m_data construction
public:
template<class T>
void init_data(std::vector<T> d)
{
init_data_helper(d,std::make_index_sequence<sizeof...(T)>{});
}
private:
template<std::size_t... index>
void init_data_helper(std::vector<T> d, std::index_sequence<index...>)//ERROR HERE
{
(std::get<index>(m_data)).SetData(d);
}
};
I would like to call the SetData method of CData class from CDataHolder class method after m_data object is constructed. The error I have got is parameter pack must be expanded in this context.

Related

Differentiate between shared_ptr and normal type on compile time

I try to create a templated class, which saves the template argument as a member variable (msg_).
Now the input of the class should allow normal types like int and shared_ptr<int>.
template <typename T>
class Foo {
public:
Foo<T>() {};
private:
T msg_;
};
My problem is if the class gets initialized with shared_ptr<int>, the shared_ptr has to get initialized:
this->msg_ = std::make_shared<T*>();
I tried to solve it like this:
Foo<T>() {
if (std::is_pointer<T>::value) {
this->msg_ = std::make_shared<T*>();
}
};
, but the problem is that is has to be solved on compile time. Otherwise I can not compile.
Do you know any patterns, which solve this issue?
Thank you! and
Best regards
Fabian
You might have specialization
template <typename T>
class Foo {
public:
Foo() {}
private:
T msg_;
};
template <typename T>
class Foo<std::shared_ptr<T>>
{
public:
Foo() : msg_(std::make_shared<T>()) {}
private:
std::shared_ptr<T> msg_;
};
or create function to initialize (with overload)
template <typename> struct tag{};
template <typename T>
T foo_default_init(tag<T>) { return {}; }
template <typename T>
std::shared_ptr<T> foo_default_init(tag<std::shared_ptr<T>>)
{
return std::make_shared<T>();
}
template <typename T>
class Foo {
public:
Foo() : msg_(foo_default_init(tag<T>{})){}
private:
T msg_;
};

can I use SFINAE to selectively define a member variable in a template class?

So what I want to do is to create a template class which may or may not contain a member variable based on the template argument passed in. like following:
template<typename T, bool flag>
class base
{
foov<std::enable_if<flag, T>::type> m_var;
};
the above code could not survive the compiler.
Does anyone know how I can achieve this?
Have a base class with enabled/disabled members based on template parameters:
template<typename T, typename Enable = void>
class base_class;
// my favourite type :D
template<typename T>
class base_class<T, std::enable_if_t<std::is_same<T, myFavouriteType>::value>>{
public:
int some_variable;
};
// not my favourite type :(
template<typename T>
class base_class<T, std::enable_if_t<!std::is_same<T, myFavouriteType>::value>>{
public:
// no variable
};
template<typename T>
class derived_class: public base_class<T>{
public:
// do stuff
};
This should give you a nice way to enable/disable members based on type.
I think this is what you are looking for.
The class template does not have any member data by default.
template<typename T, bool flag>
class base
{
};
Add a specialization of the class template that has the member data.
template<typename T>
class base<T, true>
{
foov<T> m_var;
};
#pragma once
#include <type_traits>
template <typename T, bool D, typename Enabled=void>
class Node;
template <typename T, bool D>
class Node<T, D, std::enable_if_t<D>>
{
public:
Node(const T& v) : value(v) {}
private:
T value;
Node* next = nullptr;
};
template <typename T, bool D>
class Node<T, D, std::enable_if_t<!D>>
{
public:
Node(const T& v) : value(v) {}
private:
T value;
Node* next = nullptr;
Node* prev = nullptr;
};
Single or double linked list node based on boolean flag
I have a workaround for this. Probably looks ugly but does resolve some of my issues
First I define a type with zero size:
typedef int zero[0];
Next I create a macro:
#ifndef VAR
#define VAR(Enable,YourType,VarName) \
std::conditional< Enable,YourType,zero >::type VarName
#endif
Then a class like this:
template < int Cond >
class Foo
{
VAR(Cond == 0,int,var);
void print()
{
if (!sizeof(var)) return;
//...
}
};
When you are using a result like var, check the size of it before using it. If the size is zero, it is invalid.

C++ Template, Functions define in a class?

Class.h
template<class T>
struct AStruct
{
//stuff
};
class aClass
{
template<class T>
void setStruct(const AStruct<T>& s)
{
theStruct = s;
}
private:
template<class T>
AStruct<T> theStruct; //this is not liked. "multiple template parameter lists are not allowed" are one of the errors I get...
};
Quite the mess but still, I'd like to know what can be done about it... I've tried playing around a bit but with no luck... Also, only standard library please!
template<class T>
struct AStruct{
};
template<class T> //<-- the template must be here
class aClass {
public:
void setStruct(const AStruct<T>& s){
theStruct = s;
}
private:
AStruct<T> theStruct; //<-- To construct this variable
};
If you are holding a member that is a class template, then you either need a class template, or you need to provide a type for the template parameter. It seems like you need the former:
template<class T>
class aClass
{
void setStruct(const AStruct<T>& s){
theStruct = s;
}
private:
AStruct<T> theStruct; // data member is class template
};
Remove the template<class T>
template<class T>
struct AStruct{
//stuff
};
template<class T>
class aClass{
void setStruct(const AStruct<T>& s){
theStruct = s;
}
private:
AStruct<T> theStruct;
};
You already defined AStruct to be a template

C++ specializing a member function

I need to make a class with a generic data member, that works something like istream. For all types it should be able to store data that it recieves by the << operator. I want it to work for single variables unless the class is created for char, where it should work for C strings.
template <typename T>
class foo<C>{
T* data;
public:
void operator << (T t);
};
template <typename T>
class foo<char>: public foo<T>{
public:
void operator << (char* str)
};
This is how I tried to solve it, but I get an erro saying: explicit specialization is using partial specialization syntax.
Is this what you intended?
template <typename T>
class foo
{
T* data;
public:
void operator<<(T t);
};
template <>
class foo<char>
{
public:
void operator<<(char* str);
};
If you meant to inherit behavior, you'll need something like this:
template <typename T>
class foo_impl
{
T* data;
public:
void operator<<(T t);
};
template <typename T>
class foo : public foo_impl<T>
{
};
template <>
class foo<char> : public foo_impl<char>
{
public:
void operator<<(char* str);
};
(or, even simpler by eliminating unneeded occurrences of public)
template <typename T>
class foo_impl
{
T* data;
public:
void operator<<(T t);
};
template <typename T>
struct foo : foo_impl<T>
{
};
template <>
struct foo<char> : foo_impl<char>
{
void operator<<(char* str);
};
And I would suggest some const-correctness:
template <typename T>
class foo_impl
{
T* data;
public:
void operator<<(const T& t);
};
template <typename T>
struct foo : foo_impl<T>
{
};
template <>
struct foo<char> : foo_impl<char>
{
void operator<<(const char* str);
};
You cannot specify a template type within the class declaration.
template <typename T>
class foo{
T* data;
public:
void operator << (T t);
};
Try this. It may also help to read the cplusplus.com documentation on templates. http://www.cplusplus.com/doc/tutorial/templates/

Template specialization by another template (of same class)

I'm writing an array class. This array class can contain again arrays as members. When implementing a printing function, I need specializations.
26:template <class T> class array : public vector<T>{
public:
...
string* printToString();
...
};
...
template <class T> string* array<T>::printToString(){
... // generic function
}
template <> inline string* array<double>::printToString(){
... // spezialization for double, works
}
561:template <class U> string* array<array<U>*>::printToString(){
... // does not work
}
The last definition produces
src/core/array.h:561: error: invalid use of incomplete type ‘class array<array<T> >’
src/core/array.h:26: error: declaration of ‘class array<array<T> >’
The g++ version is g++ (Ubuntu 4.4.3-4ubuntu5) 4.4.3 if that matters.
Any ideas what's the problem?
Thanks in advance,
Thomas
As an alternative to David's solution, you can unconditionally forward the call to a set of overloaded functions:
template <class T> class array;
namespace details {
template <class T> std::string array_print(array<T> const&);
std::string array_print(array<double> const&); // Regular function
template <class T> std::string array_print(array<array<T> > const&);
}
template <class T> class array : private vector<T> {
public:
...
std::string printToString() { return details::array_print(*this); }
...
};
namespace details { /* implementions after class is defined */ }
You cannot partially specialize a function, you can only fully specialize it, which is the reason why you can provide an specialization for double but not for array<U> where U is a generic type.
You can get around this limitation by using a class template, and partially specializing that, but it will be a bit cumbersome.
namespace detail {
template <typename T>
struct array_printer {
static std::string print( array<T> const & array ) {
// basic implementation
}
};
template <typename T>
struct array_printer< array<T> > {
static std::string print( array< array<T> > const & array ) {
// specialization for array<T>
}
}
}
And then implement the member function as a simple dispatch to the appropriate overload:
template <typename T>
class array : std::vector<T> { // do not publicly derive from STL containers
public:
std::string printToString() const {
return detail::array_printer<T>::print( *this );
}
}
Of course, things are a little more complex in real code, and you will have to order the code appropriatedly, and provide forward declarations of the templates and all that, but this should be enough to get you started.
Your function must be fully specialized. For example:
// Fully specialized. You cannot replace `double` with generic parameter.
template <>
string* array<array<double>*>::printToString(){
return nullptr;
}
However, your class can be partially specialized. For example:
template <class T> class array : public vector<T>{
public:
string* printToString();
};
template <class T> string* array<T>::printToString(){
return nullptr;
};
// Partial specialization.
template <class T> class array<array<T>*> : public vector<T>{
public:
string* printToString();
};
template <class T> string* array<array<T>*>::printToString(){
return nullptr;
};
-- EDIT ---
The methods from generic class will not be automatically "taken" by the class specialization, or vice-versa. You can, however use inheritance to "automate" the reuse of methods from generic class. For example...
template <class T> class array : public vector<T>{
public:
string* printToString();
void f();
};
// (1a)
template <class T> string* array<T>::printToString(){
return nullptr;
};
// (2)
template <class T> void array<T>::f(){
};
template <class T> class array<array<T>*> : public array<T> {
public:
string* printToString();
};
// (1b)
template <class T> string* array<array<T>*>::printToString(){
return nullptr;
};
void Test() {
array<double> a1;
a1.printToString(); // Calls (1a).
a1.f(); // Calls (2).
array<array<char>*> a2;
a2.printToString(); // Calls (1b).
a2.f(); // Calls (2).
}
...which may or may not be what you need (some "manual" repetition might be necessary).