Search code examples
c++templatesinner-classesassignment-operator

Template assignment operator in template class copying inner class issue


I have a template class containing an inner class. On the operator=() overload I want to copy an instance of the inner class but get an error:

no known conversion from 'const foo<double>::bar' to 'const foo<int>::bar'

The code looks like (You can find an example here):

template<typename T>
class foo {
public:
    template<typename>
    friend class foo;

    class bar {
        std::string inner_str;
    public:
        bar const& operator=(bar const& r) {
            inner_str = r.inner_str;
            return *this;
        }
    };

    template<typename F>
    foo const& operator=(foo<F> const& r) {
        value = static_cast<T>(r.value);
        str_container = r.str_container;
        return *this;
    }

private:
    bar str_container;
    T value;
};

Moving bar outside foo works fine, but the inner class should be part of foo.

How to solve this issue? I thought about making bar friend like foo is friend to all specializations of foo. But I don't know how to introduce them.

Sidenote: Please feel free to change the title since I don't really know how to title this specific problem.


Solution

  • foo<double>::bar is a completely unrelated type to const foo<int>::bar, so you cannot convert between them implicitly.

    Since bar appears to not depend on a template argument, this would seem like a sensible solution:

    Moving bar outside foo works fine

    Problem solved :)

    but the inner class should be part of foo.

    Considering how you use it, I would argue that no, it should not be part of foo.

    Alternatively, you could make the assignment operator of bar a template just like you did with the assignment operator of foo:

    template<typename B>
    bar const& operator=(const B& r) {
        inner_str = r.inner_str;
        return *this;
    }
    template<typename U>
    friend class foo<U>::bar; // this bar must be friends with other bars
    

    If the definition of bar does depend on the template argument of foo, then you could use this approach. Otherwise, it wouldn't make much sense to define an identical, but separate inner class inside every foo.