0

我想定义一个带有友元函数的模板结构,其参数类型派生自结构中定义的类型。如果相应的结构已经被实例化,友元函数应该可以在没有明确类型说明的情况下被调用。

以下方法似乎有效:

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

如果使用不依赖于结构内部的参数类型定义友元函数,则可以将接口和实现分开,如下所示:

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

现在我想知道这两种方法是否可以结合起来。以下方法不起作用(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;
}

我猜最后一种方法失败了,因为模板参数推导不适用于::。有任何想法吗?

4

2 回答 2

1

做两个小改动:

  • 朋友 void mutateC ...
  • 突变C< int >(c, 1);
于 2013-12-22T14:08:53.323 回答
0

添加一个间接级别解决了这个问题:

template <typename T> struct C;
template <typename T> void mutateC_impl(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) { mutateC_impl<T>(a, b); }
    friend void mutateC_impl<T>(typename C<T>::param_type a, typename C<T>::underlying_param_type b);
    private: T data_;
};

template <typename T> void mutateC_impl(typename C<T>::param_type a, typename C<T>::underlying_param_type b) { a.data_ = b; }
于 2013-12-23T18:41:13.453 回答