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; }
// ^^^^^
};