1

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;
}
  • https://stackoverflow.com/questions/7908248/in-a-templated-derived-class-why-do-i-need-to-qualify-base-class-member-names-w , `this->_get_value();` – rafix07 Jan 17 '22 at 21:19
  • @rafix07 No error, but `get_value()` still not working: output is nothing. – NoIdeaForUsername Jan 17 '22 at 21:32
  • post a full program, a minimal reproducible example. how are you getting a value into the template? – jwezorek Jan 17 '22 at 21:49
  • @jwezorek Edited the question – NoIdeaForUsername Jan 17 '22 at 21:54
  • 1
    @NoIdeaForUsername: Your `A` has two separate `std::string` base classes. The inherited constructors are not from the one that `extend` uses. So the `extend` class and its functions will not see the other `string` that was initialized by the inherited constructors. – Nicol Bolas Jan 17 '22 at 22:09
  • yeah the problem is the multiple inheritance. the *this that _extend has inherits from a string that was null-constructed when kc::A was created – jwezorek Jan 17 '22 at 22:12
  • @NicolBolas How can I fix this problem? – NoIdeaForUsername Jan 17 '22 at 22:15
  • @NoIdeaForUsername: I don't understand why it is you want to do *any of this*, so I can't really offer a suggestion. – Nicol Bolas Jan 17 '22 at 22:17
  • @NicolBolas I'm doing that, because I don't want to create `get_value()` in every class I extend. – NoIdeaForUsername Jan 17 '22 at 22:20
  • @NoIdeaForUsername: Why do you want *every* class to be able to "get a value", whatever that means? C++ isn't Java; "every" class isn't supposed to be able to have the same interface. Maybe some specific subset of classes, but not all of them. – Nicol Bolas Jan 18 '22 at 00:19

2 Answers2

0

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;
}
jwezorek
  • 8,592
  • 1
  • 29
  • 46
0

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