【问题标题】:Template friend function of template class that introduces a new template parameter引入新模板参数的模板类的模板友元函数
【发布时间】:2015-01-27 14:33:08
【问题描述】:

感谢 Daniel Frey 对this post 的回答,我知道如何向具有相同模板参数的模板类声明模板友元函数。不幸的是,使用附加模板参数声明友元函数的语法仍然让我无法理解。我想实现这样的目标:

template <typename T>
class Obj;

template <typename T>
Obj<T> make_obj(T t);

template <typename T, typename RetVal>
RetVal ret_obj(T t);

template <typename T>
class Obj {
private:
    T & t;
    Obj (T & t) : t(t) { }
    Obj() = delete;

    friend Obj make_obj<T>(T t);

    template <typename RetVal>
        friend RetVal ret_obj<T, RetVal>(T t);
};

template <typename T>
Obj<T> make_obj(T t) { 
    return Obj<T>(t);
}

template <typename T, typename RetVal>
RetVal ret_obj(T t) {
    return RetVal(make_obj(t).t);
}

我知道在 this post 中已经提出了相同的问题,但那里接受的答案似乎不是我想要的:将参数名称更改为 T2 使该函数成为对象,而我想保持T 与课堂上的相同。

【问题讨论】:

  • 作为猜测,我会说“你不能”。将会有一些变通方法可以使其工作,例如通过帮助器struct 反弹函数。
  • 不可能。友元声明不能声明部分特化。
  • @Yakk 是的,我想我可以使用另一个类,如果必须的话,我会这样做;我只是想知道是否有直接的方法可以做到这一点。如果没有就太糟糕了。 :(
  • @T.C.并且无论如何都没有功能的部分专业化。嗯:你能把使用别名做朋友吗?

标签: c++ templates friend


【解决方案1】:

不可能让friend 声明引用部分特化——它们要么引用特定特化,要么引用主模板。此外,函数模板无论如何都不能部分特化。
不过,函数模板无法实现的功能通常可以使用类模板来实现:

template <typename T>
struct ret_obj_helper {
    // Here goes the original definition of ret_obj - the important difference
    // is the location of the template parameter T, which is the one
    // fixed by the friend declaration below
    template <typename RetVal>
    RetVal ret_obj(T t) {return RetVal(make_obj(t).t);}
};

// I guess RetVal, having to be explicitly specified, better goes first (?)
template <typename RetVal, typename T>
RetVal ret_obj(T&& t)
{
    // Overcomplicated for the sake of perfect forwarding
    return ret_obj_helper<typename std::remove_reference<T>::type>{}.
      template ret_obj<RetVal>(std::forward<T>(t));
}

template <typename T>
class Obj {
private:
    T t;
    Obj (T t) : t(t) { }
    Obj() = delete;

    friend Obj make_obj<T>(T t);

    // Make all specializations of the member function template 
    // of ret_obj_helper<T> a friend, regardless of the return type
    template <typename RetVal>
    friend RetVal ret_obj_helper<T>::ret_obj(T t);
};

Demo.

【讨论】:

  • 是的,我知道在阅读了上面的 cmets 后会归结为这一点。只是一个问题:如果没有删除引用,用 one 调用函数就不会编译?
  • 使用公共结构而不是公共静态成员有什么好处?我看不出封装程度有什么不同。由于 public 函数不能成为朋友,它必须通过一个丑陋的 public 接口。
猜你喜欢
  • 2010-12-19
  • 1970-01-01
  • 2016-10-19
  • 2013-09-18
  • 1970-01-01
  • 2011-07-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多