I have this templated base class:
template <class V>
class ValueParam
{
public:
virtual V convert(const char* f) const = 0;
protected:
V val;
};
Note that I can store some value val that has type V, and that I have a convert function that automatically returns the right type when I call it on a ValueParam object.
An example with int as type V:
class IntParam : public ValueParam<int>
{
public:
IntParam(int i) { val = i; }
int convert(const char* f) const override { return atoi(f); }
};
Which we can then use:
IntParam i(1234); // The value of val is 1234
int x = i.convert("1"); // x will be 1
Now I bump into a problem when using char* as my type V:
class StrParam : public ValueParam<char*>
{
public:
StrParam(const char* str, size_t max_len)
{
val = new char[max_len 1]{};
strncpy(val, str, max_len 1);
}
~StrParam() { delete[] val; }
char* convert(const char* f) const override { return f; } // Doesn't compile: f is const char*
};
I don't want to do any const-casting.
Luckily, I don't need the result of convert to be mutable in any way. Could I change its return type to something that does compile?
And what would that type be? Because just changing it to virtual const V convert... would mean the return type in StrParam would become char* const convert... and that obviously still doesn't work.
CodePudding user response:
You can add const on the pointed type for the return type:
// for non-pointer type
template <typename T>
struct add_const_pointee { using type = T; };
// for pointer type
template <typename T>
struct add_const_pointee<T*> { using type = const T*; };
// helper type
template <typename T>
using add_const_pointee_t = typename add_const_pointee<T>::type;
template <class V>
class ValueParam
{
public:
virtual add_const_pointee_t<V> convert(const char* f) const = 0;
// ^^^^^^^^^^^^^^^^^^^^^^
protected:
V val;
};
and
class StrParam : public ValueParam<char*>
{
public:
StrParam(const char* str, size_t max_len)
{
val = new char[max_len 1]{};
strncpy(val, str, max_len 1);
}
~StrParam() { delete[] val; }
const char* convert(const char* f) const override { return f; }
// ^^^^^
};
