模板结构的友元函数,参数类型取决于结构的内部

时间:2013-12-22 13:49:43

标签: c++ templates struct friend-function

我想用友元函数定义模板化结构,其参数类型是从结构中定义的类型派生的。如果相应的结构已经实例化,那么friend函数应该是可调用的,而不需要显式类型规范。

以下方法似乎有效:

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

如果使用不依赖于结构内部的参数类型定义friend函数,则可以按如下方式分离接口和实现:

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

我猜最后一种方法失败,因为模板参数推断不能在::。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

做两处小改动:

  • 朋友无效mutateC ...
  • mutateC&LT; int&gt;(c,1);

答案 1 :(得分: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; }