Home > OS >  Template class char*, return type of function const char*?
Template class char*, return type of function const char*?

Time:12-13

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