0

I am reading the book Advanced C++ Metaprogramming and I encounter that a snippet of code at section 2.2.3. (page 49th) doesn't compile (My current compiler is Visual Studio 2013). The error arises at assignment but the book says that the assignment "ok: it ends up calling basic_inner::operator=". Did I miss something?

template <typename X, typename T>
struct basic_inner
{
    template <typename T2>
    basic_inner& operator=(const basic_inner<X, T2>&)
    {
        // do something...
        return *this;
    }
};

template <typename T>
struct outer
{
    template <typename X>
    struct inner : public basic_inner<X, T>
    {
        inner& operator=(const basic_inner<X, T> &that)
        {
            static_cast<basic_inner<X, T>&>(*this) = that;
            return *this;
        }
    };
};

template <>
struct outer<int>
{
    template <typename X>
    struct inner : public basic_inner<X, int>
    {
        inner& operator=(const basic_inner<X, int> &that)
        {
            static_cast<basic_inner<X, int>&>(*this) = that;
            return *this;
        }
    };
};

The client code is:

outer<double>::inner<void> x1;
outer<int>::inner<void> x2;

x1 = x2;    // <-- error: no operator found which takes right-hand operand of type 'outer<int>::inner<void>'(or there is no acceptable conversion)
3
  • Most textbooks have dodgy code - check the authors website, they usually sheepishly admit this from time to time. Even better, fix it and email them - they really don't like that. Commented Apr 12, 2014 at 16:06
  • Does the book present a motivation for this weird code? Commented Apr 12, 2014 at 16:23
  • @jrok Sorry I can't realize its presentation. I guess that the inner classes of different specialization have the same detail so that they could been assigned each other. Commented Apr 12, 2014 at 16:45

1 Answer 1

1

I guess that assignment operator of basic_inner class is not visible in your derived class inner, due to name hiding. You can put using basic_inner<X, T>::operator=; to your outer class and get something like this.

template <typename T>
struct outer {
  template <typename X>
  struct inner : public basic_inner<X, T> {
    using basic_inner<X, T>::operator=;
    inner& operator=(const basic_inner<X, T>& that) {
      static_cast<basic_inner<X, T>&>(*this) = that;
      return *this;
    }
  };
};

template <>
struct outer<int> {
  template <typename X>
  struct inner : public basic_inner<X, int> {
    using basic_inner<X, int>::operator=;
    inner& operator=(const basic_inner<X, int>& that) {
      static_cast<basic_inner<X, int>&>(*this) = that;
      return *this;
    }
  };
};
Sign up to request clarification or add additional context in comments.

1 Comment

+1, but... I'd guess that this isn't what the author of the code intended. With using declaration, neither the inner::operator= nor the one in the explicit specialization get called. See here (note the cout statements and the output). This code got me completely perplexed, wtf.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.