简体   繁体   English

附加模板 arguments 用于模板 class 中的朋友声明?

[英]Additional template arguments for friend declaration in template class?

In order for some global function为了一些全球function

template<typename T, int count>
void func (const Obj<T>& obj) {
    for (int i = 0; i < count; i++)
        std::cout << obj.value << std::endl;
}

to be able to access to the private field value of some templated class能够访问某些模板化 class 的私有字段value

template<typename T>
class Obj {
    public:
        Obj (T value);
    private:
        T value;
};

template<typename T>
Obj<T>::Obj (T value) : value(value) {}

we need to declare func<T, count> a friend of Obj<T> .我们需要将func<T, count>声明为Obj<T>的朋友。 But func<T, count> has to be declared before we can make it a friend of Obj<T> , and for this we need to forward-declare Obj<T> .但是func<T, count>必须先声明,然后才能使其成为Obj<T>的朋友,为此我们需要前向声明Obj<T> The resulting code looks like this生成的代码如下所示

// Forward declarations
template<typename T>
class Obj;

template<typename T, int count>
void func (const Obj<T>& obj);

// Obj<T>
template<typename T>
class Obj {
    public:
        Obj (T value);

        template<int count>
        friend void func<T, count> (const Obj<T>& obj);
    private:
        T value;
};

template<typename T>
Obj<T>::Obj (T value) : value(value) {} // <-- ERROR

// func<T>
template<typename T, int count>
void func (const Obj<T>& obj) {
    for (int i = 0; i < count; i++)
        std::cout << obj.value << std::endl;
}

But this makes gcc complain about the "invalid use of template-id 'func' in declaration of primary template", so how do I actually declare func<T, count> a friend of Obj<T> for every count ?但这使得 gcc 抱怨“在主模板声明中无效使用模板 ID 'func'”,那么我如何实际声明func<T, count>Obj<T>的每个count的朋友? According to this answer I just need to replace the friend declaration with this根据这个答案,我只需要用这个替换朋友声明

template<typename T1, int count>
friend void func (const Obj<T1>& obj);

As far as I know this would make func<T1, count> a friend of Obj<T> regardless of whether T1 and T match, which is absurd.据我所知,这将使func<T1, count>成为Obj<T>的朋友,无论T1T是否匹配,这是荒谬的。 Is it possible to declare func<T, count> a friend of Obj<T> and no other Obj<T1> ?是否可以将func<T, count>声明为Obj<T>的朋友而没有其他Obj<T1> (preferably in a way that keeps the definition of func<T, count> outside the definition of Obj<T> ) (最好将func<T, count>的定义保持在Obj<T>的定义之外)

(I know I could just make count a real parameter, but the example above is just a simplification of my real code. In reality I'm trying to overload std::basic_ostream<CharT, Traits>& operator<< (std::basic_ostream<CharT, Traits>& stream, const Obj<T>& obj) for some class Obj<T> in a way that allows operator<< to access private fields of Obj<T> .) (我知道我可以让count成为一个真实的参数,但上面的例子只是我真实代码的简化。实际上我试图重载std::basic_ostream<CharT, Traits>& operator<< (std::basic_ostream<CharT, Traits>& stream, const Obj<T>& obj)用于某些 class Obj<T>以允许operator<<访问Obj<T>的私有字段。)

The friend declaration must match any possible forward declaration, and of course the definition, including template arguments. friend元声明必须匹配任何可能的前向声明,当然还有定义,包括模板 arguments。

That means you need eg这意味着你需要例如

template<typename U, int count>
friend void func(const Obj<U>& obj);

It doesn't matter if the class template argument T and the function template argument U are different, as the calls will be made to the correct function anyway. class 模板参数T和 function 模板参数U是否不同并不重要,因为无论如何都会对正确的 function 进行调用。

Example:例子:

Obj<int> int_obj;
Obj<float> float_obj;

func<X>(int_obj);  // Will call void func<int, X>(int_obj)
func<X>(float_obj);  // Will call void func<float, X>(float_obj)

As an alternative, you can define the function inline in the class definition, and then you don't need to provide the T or U template arguments:作为替代方案,您可以在 class 定义中定义function 内联,然后您不需要提供TU模板 arguments:

template<int count>
friend void func(const Obj<T>& obj)
{
    // Implementation...
}

And in neither case you should really have a forward declaration of func (as mentioned in my comment).在这两种情况下,您都应该真正拥有func的前向声明(如我的评论中所述)。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM