Private class specialization error - c++

During compilation the code below in clang i have warning (in vc++ it works fine):
warning : explicit specialization of 'Helper' within class scope is a
Microsoft extension [-Wmicrosoft]
#include <stdio.h>
#include <string>
enum class Car { BMW };
class C
{
static void Method() { puts("inner");}
};
template<typename T>
class BaseClass
{
private:
template<typename V>
struct Helper;
template<>
struct Helper<Car>
{
typedef C InnerType;
static const char* Name() { return "Car"; }
};
typedef Helper<T> Info;
typedef typename Info::InnerType InnerType;
private:
T v;
protected:
BaseClass()
{ }
public:
T Value() const { return v; }
std::string Name() const { return Info::Name(); }
static void Print() { InnerType::Method(); }
};
class MyCar : public BaseClass<Car>
{
public:
MyCar() : BaseClass() {}
};
int main()
{
MyCar a;
printf("%s\n", a.Name().c_str());
// a.Print();
}
I have tried to move the specialization of Helper class outside BaseClass to be compatible with standard:
template<> template<>
struct BaseClass<Car>::Helper<Car>
{
typedef C InnerType;
static const char* Name() { return "Car"; }
};
But now I have compilation error:
error: implicit instantiation of undefined template 'BaseClass::Helper'
If I remove the line: typedef typename Info::InnerType InnerType; (and related usage in function Print) then everything works fine.
Is it possible to fix this error ? I would like to keep my Helper class as private.

You can do it like this:
#include <stdio.h>
#include <string>
enum class Car { BMW };
class C
{
static void Method() { puts("inner");}
};
template<typename T>
class BaseClass
{
private:
template<typename V>
struct Helper;
template<typename V>
using Info = Helper<V>;
template<typename V>
using InnerType = typename Info<V>::InnerType;
private:
T v;
protected:
BaseClass()
{ }
public:
T Value() const { return v; }
std::string Name() const { return Info<T>::Name(); }
static void Print() { InnerType<T>::Method(); }
};
template<> template<>
struct BaseClass<Car>::Helper<Car>
{
typedef C InnerType;
static const char* Name() { return "Car"; }
};
class MyCar : public BaseClass<Car>
{
public:
MyCar() : BaseClass() {}
};
int main()
{
MyCar a;
printf("%s\n", a.Name().c_str());
//a.Print();
}
(gcc 5.1/clang 3.6, -std=C++11)
The program prints "Car".

Related

What is the difference between class and struct in the "Type Erasure" code by using std::make_shared in C++?

I am trying to understand the behavior of "Type Erasure" by using std::make_shared. The basic idea is to use a class Object to wrap some different classes, such as class Foo and class Bar.
I write the following code, and it does work.
// TypeErasure.cpp
#include <iostream>
#include <memory>
#include <string>
#include <vector>
class Base
{
public:
virtual ~Base() {}
virtual std::string getName() const = 0;
};
template< typename T >
struct Derived : Base
{
public:
explicit Derived(const T&& t) : objD(t) {}
std::string getName() const override
{
return objD.getName();
}
private:
T objD;
};
class Object
{
public:
template <typename T>
explicit Object(T&& t)
: objPtr(std::make_shared<Derived<T>>(std::forward<T>(t))) {}
std::string getName() const
{
return objPtr->getName();
}
std::shared_ptr<const Base> objPtr;
};
void printName(std::vector<Object> vec)
{
for (auto v: vec) std::cout << v.getName() << std::endl;
}
class Bar
{
public:
std::string getName() const
{
return "Bar";
}
};
class Foo
{
public:
std::string getName() const
{
return "Foo";
}
};
int main()
{
std::vector<Object> vec{Object(Foo()), Object(Bar())};
printName(vec);
}
but when I change "struct Derived : Base" into "class Derived : Base", it shows the following error.
error: no matching function for call to 'std::shared_ptr::shared_ptr(std::shared_ptr)'|
The code is as following.
// TypeErasure.cpp
#include <iostream>
#include <memory>
#include <string>
#include <vector>
class Base
{
public:
virtual ~Base() {}
virtual std::string getName() const = 0;
};
template< typename T >
class Derived : Base
{
public:
explicit Derived(const T&& t) : objD(t) {}
std::string getName() const override
{
return objD.getName();
}
private:
T objD;
};
class Object
{
public:
template <typename T>
explicit Object(T&& t)
: objPtr(std::make_shared<Derived<T>>(std::forward<T>(t))) {}
std::string getName() const
{
return objPtr->getName();
}
std::shared_ptr<const Base> objPtr;
};
void printName(std::vector<Object> vec)
{
for (auto v: vec) std::cout << v.getName() << std::endl;
}
class Bar
{
public:
std::string getName() const
{
return "Bar";
}
};
class Foo
{
public:
std::string getName() const
{
return "Foo";
}
};
int main()
{
std::vector<Object> vec{Object(Foo()), Object(Bar())};
printName(vec);
}
What is the root cause of this error?
Is it about the difference between class and struct?
Is it because class is a reference and struct is a value?
The only real difference between a class and a struct in C++ is that, for a struct, the default member access and inheritance is public, whereas, for a class, the default is private.
So, to make your code work for the class Derived template, just make its inheritance of Base public:
template< typename T >
class Derived : public Base { // public inheritance
public:
//...
Such public inheritance gives the Derived class access to the Base class constructors.
Alternatively, to make your struct template case fail – most likely with the exact same error message(s) – you can make its inheritance of Base private:
template< typename T >
struct Derived : private Base { // private inheritance - fails to compile!
public:
//...

How to get the value of a template class?

I'm trying to get the value of a template class. To get the value of a class, I can easily do like:
int get_value()
{
return *this;
}
But I want to create a class, and extend it, and don't make get_value() in all classes again. So, I did that:
template<typename T>
class _extend : public T
{
public:
auto _get_value()
{
return *this;
}
};
template<typename T>
class extend : public _extend<T>
{
public:
T get_value()
{
auto value = this->_get_value(); /* It was `_get_value()`, changed to `this->_get_value()` due to the comments */
T output = value;
return output;
}
};
But it's not working: output is nothing.
Edit
Sample program:
#include <iostream>
namespace kc
{
template<typename T>
class _extend : public T
{
public:
auto _get_value()
{
return *this;
}
};
template<typename T>
class extend : public _extend<T>
{
public:
T get_value()
{
auto value = this->_get_value();
T output = value;
return output;
}
};
class A : public std::string, public extend<std::string>
{
public:
using std::string::string;
};
}
int main()
{
kc::A a("a");
std::cout << a.get_value() << std::endl;
}
The problem with the code in the question is the multiple inheritance. The *this that _extend<string>::get_value() will be called with is not the string that has a value.
Although I agree with #NicolBolas in comments in that I don't understand why you want this, but you can make a class template that will return the value of what it derives from with only one level of inheritance. You just need to give it a perfect forwarding constructor and have get_value() cast to the base type, i.e.
#include <iostream>
#include <string>
namespace kc
{
template<typename T>
class extend : public T
{
public:
template<typename... Args>
extend(Args&&... args) : T(std::forward<Args>(args)...)
{}
T get_value()
{
return *static_cast<T*>(this);
}
};
}
int main()
{
kc::extend<std::string> a("foo");
std::cout << a.get_value() << std::endl;
}
Basically:
template<class C>
class extend : public C
{
public:
using C::C;
auto get()
{
return *this;
}
};
And a full example:
#include <iostream>
template<class C>
class extend : public C
{
public:
using C::C;
auto get()
{
return *this;
}
};
class e_string : public extend<std::string>
{
public:
using extend<std::string>::extend;
};
int main()
{
e_string s = "Test";
std::cout << s.get() << std::endl;
}

How can I implement an assignment operator in a class template?`

I thought my problem was answered by this, but I can't get the following to compile:
#include <string>
template<class C>
class tKeySet {
protected:
bool set;
static const std::string key;
};
template<class C, typename T>
class tKeySetType : private tKeySet<C> {
protected:
T m_val;
};
template<class C>
class tKeySetString: private tKeySetType<C, std::string> {
public:
tKeySetString<C>& operator=(const std::string &str) {
this->set = true;
this->m_val = str;
return *this;
}
};
class foo : private tKeySetString<foo> { };
template<> const std::string tKeySet<foo>::key = "foo key";
int main(void) {
foo f;
f = std::string("foo");
return 0;
}
How can I make the assignment operator in tKeySetString<C> work with std::string?
foo privately inherits from tKeySetString<foo>, which means that operator= will not be part of its public interface.
You can bring it in by writing
public:
using tKeySetString::operator=;
in the definition of foo.

How to handle class with multiple data members of different type in c++?

Suppose I have a class which has many data members of different type, and maybe add more in future
Class A
{
public:
int getA();
void setA(int a);
...
private:
int m_a;
int m_b;
double m_c;
string m_d;
CustomerType m_e;
char * m_f;
...
}
the problem is: each time I add a another data member, I need to add get/set function. For some reason I cannot change them to public.
one solution is to use getType/setType function together with template:
Class A
{
public:
int getInt(int id){
switch(id)
case ID_A:
return m_a;
case ID_B:
return m_b;
...
}
void setInt(int id,int i){...}
double getDouble(){...}
void setDouble(int id,double d){...}
...
template<T>
T get();
template<> //specialize
double get<double>(){return getDouble();}
...
private:
}
Is there any better solution? Thanks.
Here's a strategy that works for me.
#include <string>
struct CustomerType {};
class A
{
public:
template <typename T> struct member
{
typedef T type;
type data;
};
struct type_A : member<int> {};
struct type_B : member<int> {};
struct type_C : member<double> {};
struct type_D : member<std::string> {};
struct type_E : member<CustomerType> {};
struct type_F : member<char*> {};
template <typename T>
typename T::type get()
{
return ((T&)allData).data;
}
template <typename T>
void set(typename T::type d)
{
((T&)allData).data = d;
}
private:
struct AllData : type_A,
type_B,
type_C,
type_D,
type_E,
type_F {};
AllData allData;
};
int main()
{
A a;
a.set<A::type_A>(20);
int b = a.get<A::type_A>();
return 0;
}

c++ polymorphism : return type of a virtual method

My main class is :
class Data{
public:
Data(std::string name):name_(name){};
virtual ~Data(){};
protected:
std::string name_;
};
Since I'd like to allow any kind of data, I use a template to create my inherited class :
template<typename Type>
class GenericData : public Data{
public:
GenericData(std::string name, Type t);
private:
Type t_;
};
template<typename Type>
GenericData<Type>::GenericData(std::string name, Type t):
Data(name),
t_(t)
{}
The third class is a collection of (Generic)Data :
class Input{
public:
Input();
~Input();
private:
std::vector<Data*> d_;
};
Input::Input(){
d_.push_back(new GenericData("double",3.2);
d_.push_back(new GenericData("int",2);
}
Input::~Input(){
for(unsigned int i(0);i<d_.size();i++){
delete d_[i];
d_[i] = NULL;
}
}
The thing that I don't know how to do is to get the t_ value from from the Input class. I'd like to have a templata<typename Type> Type Input::get(unsigned int i) method that returns t_. I guess that I should create a virtual method in Data and another method in GenericData but I can't make it work.
It's pretty straightforward:
#include <string>
#include <vector>
#include <iostream>
class Data{
public:
Data(std::string name):name_(name){};
virtual ~Data(){};
protected:
std::string name_;
};
template<typename Type>
class GenericData : public Data{
public:
GenericData(std::string name, Type t);
Type Get() { return t_; }
private:
Type t_;
};
template<typename Type>
GenericData<Type>::GenericData(std::string name, Type t):
Data(name),
t_(t)
{}
class Input{
public:
Input() {}
~Input();
void Add(Data*v) {d_.push_back(v);}
template<typename T>
T Get(int i) {
return dynamic_cast< GenericData<T> *>(d_[i])->Get();
}
private:
std::vector<Data*> d_;
};
Input::~Input(){
for(unsigned int i(0);i<d_.size();i++){
delete d_[i];
d_[i] = NULL;
}
}
int main() {
Input inp;
inp.Add(new GenericData<int>("1", 1));
inp.Add(new GenericData<double>("2", 2.0));
std::cout << "1: " << inp.Get<int>(0) << "; 2: " << inp.Get<double>(1) << std::endl;
return 0;
}
That's quite problematic. First of all, you have to provide some way to get it from Data, for example:
(inside GenericData)
public:
T GetValue()
{
// Consider naming t_ more informative
return t_;
}
Secondly, you can create a generic method for getting data in Input:
(inside Input)
public:
template <typename T>
GenericData<T> * GetData(int index)
{
return dynamic_cast<GenericData<T> *>(_d[index]);
}
or, simpler:
(inside Input)
public:
template <typename T>
T GetValue(int index)
{
return (dynamic_cast<GenericData<T> *>(_d[index]))->GetValue();
}