While I've seen a few posts regarding taking in template classes as a parameter into a template class I can't seem to find something that works with my code, or simply I do not understand the explanation well enough.
Ultimately, I'm looking for a template class that takes another template class which takes a standard class.
*Note: For brevity, I've only included what I believe to be sufficient information.
I've made an attempt based on the information I could find and it is shown here:
Concrete Class
class ConcreteClass {
private:
std::string words;
public:
ConcreteClass(std::string newWords);
};
#endif
Template Class template
template <class ConcreteClass>
class TemplateClass{
private:
ConcreteClass stuff;
public:
TemplateClass(ConcreteClass fillStuff);
};
#endif
template <class ConcreteClass>
TemplateClass<ConcreteClass>::TemplateClass(ConcreteClass fillStuff) {
stuff = fillStuff;
}
Base Class template
template<template<class> ConcreteClass, class TemplateClass>
class BaseClass {
private:
TemplateClass<ConcreteClass>* objPntr;
}
template<template<class> ConcreteClass, class TemplateClass>
BaseClass<TemplateClass<ConcreteClass>::BaseClass(TemplateClass<ConcreteClass>* newObj) {
objPntr = newObj;
}
template<template<class> ConcreteClass, class TemplateClass>
BaseClass<TemplateClass<ConcreteClass>::~BaseClass() {
if(objPntr) {
delete objPntr;
}
}
Main
int main() {
ConcreteClass cClass("some values");
TemplateClass tClass(cClass);
BaseClass(tClass);
return 0;
}
Firstly, you need a class or typename keyword before the template parameter name in the case of template-templates. Secondly, you should put the template<class> before TemplateClass, not ConcreteClass. TemplateClass is your templated type, so it needs that specifier:
#include <string>
// I had to make up your types because there is no definition for them
struct ConcreteClass {
std::string value;
};
template <typename T>
struct TemplateClass {
T t;
};
template<class ConcreteClass, template<class> class TemplateClass>
class BaseClass {
private:
TemplateClass<ConcreteClass>* objPntr;
// constructor needs to be declared before being defined
public:
BaseClass(TemplateClass<ConcreteClass> *objPntr);
};
template<class ConcreteClass, template<class> class TemplateClass>
BaseClass<ConcreteClass, TemplateClass>::BaseClass(TemplateClass<ConcreteClass>* newObj) {
objPntr = newObj;
}
int main() {
ConcreteClass cClass{"some values"};
TemplateClass<ConcreteClass> tClass{cClass};
BaseClass<ConcreteClass, TemplateClass> bClass(&tClass);
}
Related
Given a codesnippet that looks like this, how can i write a function, that checks if a given object implements a certain mixin? I tried using pointer-casting but since they have the same base every resoult was non-null, but I am guessing there is a templated solution, but couldn't find any I could implement.
class Widget{
public:
int px;
int py;
};
template <typename Base>
class StaticText : public Base{
public:
std::string text;
};
template <typename Base>
class Alignable : public Base{
public:
std::string alignment;
};
template <typename Base>
class Colorable : public Base{
public:
std::string color;
};
typedef Alignable<StaticText<Widget>> Text;
int main(){
auto w = std::make_unique<Text>();
// if(w == Colorable...)
// if(w == Alignable...)
std::cin.get();
return 0;
}
You could do something like this:
template <template <class> class Z, class T>
class implements_mixin
{
template <class U>
static std::true_type test(Z<U>* );
static std::false_type test(... );
public:
using type = decltype(test(std::declval<T*>()));
static constexpr bool value = type::value;
};
template <class T>
using isColorable = implements_mixin<Colorable, T>;
// etc.
If there exists a U such that T inherits from Z<U>, we consider that mixin implemented. So implements_mixin<Colorable, Test>::type is std::false_type, but implements_mixin<StaticText, Text>::type is std::true_type.
I'm trying to write a template class that defines its template based on the template implementation of a interface. To clarify my problem, here a example.
template<typename T>
class A{
virtual T getValue() = 0;
}
class B : public A<int>{
//does some things and implements getValue
}
//template definition
//T should become int by passing class B
class C{
A* aPointer;
T previousValue;
}
I've tried template template (not a typing error) syntax, explained really nice in this post. What are some uses of template template parameters in C++?. But because the type of A is determent in the definition of B it doesn't work.
How should i go about and create a template that determines T.
You can't determine the type of T directly from B, but you can from its interface. The best way of handling this would be to add a typedef of T to A.
template<typename T>
class A{
virtual T getValue() = 0;
public:
typedef T ValueType;
}
class B : public A<int>{
//does some things and implements getValue
}
template<class T>
class C {
A<typename T::ValueType>* aPointer;
typename T::ValueType previousValue;
}
Define a named type alias in class interfaces.
The standard library also does this.
template<typename T>
class A{
public:
using value_type = T;
virtual value_type getValue() = 0;
};
class B : public A<int>{
public:
using A<int>::value_type;
//does some things and implements getValue
value_type getValue() override { return 0; }
};
//template definition
//T should become int by passing class B
template<class Derived>
class C{
public:
using value_type = typename Derived::value_type;
A<value_type>* aPointer;
value_type previousValue;
};
int main()
{
C<B> c;
auto x = c.aPointer->getValue();
}
You can use a support function of which you don't even have to give a definition.
It follows a minimal, working example:
#include<type_traits>
#include<utility>
template<typename T>
class A{};
class B : public A<int>{};
template<typename T>
T a_type(const A<T> &);
template<typename T>
class C {
public:
using type = decltype(a_type(std::declval<T>()));
};
int main() {
static_assert(std::is_same<C<B>::type, int>::value, "!");
}
The good part of this approach is that you don't have to modify neither A nor B.
Can we specialize a template class for a templated class?
template<>
class Storage8<MyClass<T>>
{
—
—
};
Here MyClass is a templated class. Is the above valied? Where do we have to mention
template for MyClass?
This should work:
// class templae for Storage8. It can just be a forward declaration
template <typename T> class Storage8;
// or a default defintion.
template <typename T> class Storage8
{
};
// Class templae for MyClass
template <typename T>
class MyClass
{
};
// Specialization of Storage8 for MyClass<T>
template <typename T>
class Storage8<MyClass<T>>
{
};
You totally can. Example:
#include <vector>
using std::vector;
template<typename T>
struct X {
static const int A = 0;
};
template<typename U>
struct X<vector<U> > {
static const int A = 1;
};
int main() {
static_assert(X<vector<int> >::A == 1, "fail");
return 0;
}
If I have a class which takes variadic pack of template arguments how can I declare them all to be friends?
Here is what I would like to do in pseudo-code form:
template<typename... Ts>
class AbstractMyClass {
int privateInt;
friend Ts...;
};
class OtherClass;
using MyClass = AbstractMyClass<OtherClass>;
class OtherClass {
public:
void foo(MyClass &c){
c.privateInt = 42;
}
};
This can only be done using "compile time recursion", much like tuples. The gist is (I am on a small laptop right now and by no means able to comfortably type):
template<class .... THINGS> class object;
template<class T> class object {
friend T;
};
template<class T,class ... THINGS>
class object: public object<THINGS> {
friend T;
};
If C++ doesn't like that, try template<> class object<> {}; as the one that ends the recursion (I terminate it with an object in 1 template paramater)
(Thanks to Dietmar Kuhl for formatting)
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