Specialized inheritance of a template class forces the member function to return the template type of the class, rather than the inherited class type

Suppose I have a base class:

template<typename T>
class Base {
public:
    Base& operator()(const T& value) {
        this->value = value;
        return *this;
    }
    T value;
};

Now I want to inherit from this class to create classes like

class InheritedFloat : public Base<float> {} inheritedFloat;

Now I'm trying to catch this inheritance in functon:

void function(const InheritedFloat& inherited) {
    std::cout << inherited.value << '\n';
}

Calling this function like this works fine, of course:

int main() {
    function(inheritedFloat); //(inheritedFloat is a global instance)

    return 0;
}

But when I try to call it using a member function operator()(const float& value){...}, it function(const InheritedFloat& inherited){...}does not see it as InheritedFloat-Type, but instead Base<float>-Type:

int main() {
    function(inheritedFloat(10.f)); //error

    return 0;
}

Error:

Error   C2664   'void function(const InheritedFloat &)': cannot convert argument 1 from 'Base<float>' to 'const InheritedFloat &'

So how can I do operator()(const T& value){...}return InheritedFloat&instead Base<float>&?


To clarify, this is just a simplified example (of course). I have dozens of inheritance cases. So I can’t just specify a templatefunction()

template<typename T>
void function(const Base<T>& inherited) {
    std::cout << inherited.value << '\n';
}

-. , , , Base<std::size_t > .

:

#include <iostream>

template<typename T>
class Base {
public:
    Base& operator()(const T& value) {
        this->value = value;
        return *this;
    }
    T value;
};

class InheritedFloat : public Base<float> {} inheritedFloat;


void function(const InheritedFloat& inherited) {
    std::cout << inherited.value << '\n';
}

int main() {
    function(inheritedFloat(10.f));

    return 0;
}

, !

+4
1

CRTP. , :

#include <iostream>

template<typename Derived, typename T>
class Base {
public:
    Derived & operator()(const T& value) {
        this->value = value;
        return *static_cast<Derived *>(this);
    }
    T value;
};

class InheritedFloat : public Base<InheritedFloat, float> {} inheritedFloat;


void function(const InheritedFloat& inherited) {
    std::cout << inherited.value << '\n';
}

int main() {
    function(inheritedFloat(10.f));

    return 0;
}

-

+10

Source: https://habr.com/ru/post/1693589/


All Articles