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/
Related
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_;
};
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.
I have two classes class A and class B both of them are template classes for a member function in A I want it to act in a special way when the type of A is B
and in a normal way for any other types I don't know how to do this ?
template <class B>
class B
{
private:
T m;
public:
...... any member functions
}
template <class T>
class A
{
private:
T var;
public:
void doSomething();
};
template <class T>
void A<T>::doSomething(){...........//implementation}
template <class T>
void A<B<T>>::doSomething(){................//different implementation}
You can specialize A this way:
template <class T>
class A<B<T>> {
// ...
};
This is an instance of partial template specialization.
If you refuse to specialize the entire class, you can defer the work from A<T>::doSomething() to a function doSomethingForA<T>(A &) that would be partially specialized, and that would possibly be friend of A<T>.
Hope this solves your problem:
#include <iostream>
template <typename T>
struct B {};
template <typename T> struct A;
template <typename T>
void doSomething(T&) { std::cout << "General\n"; }
template <typename T>
void doSomething(A<B<T>>&) { std::cout << "Special\n"; }
template <typename T>
struct A {
void doSomething() {
::doSomething(*this);
}
};
int main()
{
A<int> general;
A<B<int>> special;
general.doSomething();
special.doSomething();
}
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
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).