Friend function of the structure modeled with argument types according to the internal elements of the structure

advertisements

I would like to define a templated structure with a friend function whose argument types are derived from types defined within the structure. The friend function should be callable without explicit type specification if the corresponding structure has been instantiated.

The following approach seems to work:

template <typename T> struct A {
    typedef T const& underlying_param_type;
    typedef A<T>& param_type;
    friend void mutateA(param_type a, underlying_param_type b) { a.data_ = b; }
    T data_;
};

If one defines the friend function with parameter types that do not depend on internals of the structure it is possible to separate interface and implementation as follows:

template <typename T> struct B;
template <typename T> void mutateB(B<T>& a, T const& b);

template <typename T> struct B {
    friend void mutateB <> (B<T>& a, T const& b);
    T data_;
};

template <typename T> void mutateB(B<T>& a, T const& b) { a.data_ = b; }

Now I am wondering whether both approaches can be combined. The following approach does not work (clang++ 3.3, g++ 4.8.2, -std=c++11):

template <typename T> struct C;
template <typename T> void mutateC(typename C<T>::param_type a, typename C<T>::underlying_param_type b);

template <typename T> struct C {
    typedef T const& underlying_param_type;
    typedef C<T>& param_type;
    friend void mutateC <> (typename C<T>::param_type a, typename C<T>::underlying_param_type b);
    T data_;
};

template <typename T> void mutateC(typename C<T>::param_type a, typename C<T>::underlying_param_type b) { a.data_ = b; }

int main() {
    A<int> a;
    mutateA(a, 1);

    B<int> b;
    mutateB(b, 1);

    C<int> c; // error: no function template matches function template specialization 'mutateC'
    mutateC(c, 1);

    return 0;
}

I guess that the last approach fails since template argument deduction does not work across ::. Any ideas?


Make two little changes:

  • friend void mutateC ...
  • mutateC< int >(c, 1);