How to declare a friend function of a template class?

Discussion in 'C++' started by Rui Maciel, Jul 12, 2010.

  1. Rui Maciel

    Rui Maciel Guest

    I have a class which has a set of friend functions. Now I wish to convert that class to a template
    class but I'm having trouble declaring the friend functions of that template class. Can anyone
    help? Any tip is more than welcomed.


    Thanks in advance,
    Rui Maciel
    Rui Maciel, Jul 12, 2010
    #1
    1. Advertising

  2. On 7/12/2010 4:08 PM, Rui Maciel wrote:
    > I have a class which has a set of friend functions. Now I wish to convert that class to a template
    > class but I'm having trouble declaring the friend functions of that template class. Can anyone
    > help? Any tip is more than welcomed.


    class Boo { // has all instance of 'Foo' as friends
    template<class T> friend class Foo;
    };

    If that doesn't fit your needs, perhaps you need to be more specific
    (and post some code this time).

    V
    --
    I do not respond to top-posted replies, please don't ask
    Victor Bazarov, Jul 12, 2010
    #2
    1. Advertising

  3. Rui Maciel <>, on 12/07/2010 21:08:03, wrote:

    > I have a class which has a set of friend functions. Now I wish to convert that class to a template
    > class but I'm having trouble declaring the friend functions of that template class. Can anyone
    > help? Any tip is more than welcomed.


    It's a bit tricky, but possible:

    //-------
    template<class T> class foo {
    public:
    foo(T t): t(t) {}
    protected:
    T t;
    template<class U> friend void inspect_foo(foo<U> f);
    };

    template<class T> void inspect_foo(foo<T> f) {
    cout << f.t << endl;
    }
    //-------


    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
    Francesco S. Carta, Jul 12, 2010
    #3
  4. Francesco S. Carta <>, on 12/07/2010 22:29:59, wrote:

    > Rui Maciel <>, on 12/07/2010 21:08:03, wrote:
    >
    >> I have a class which has a set of friend functions. Now I wish to
    >> convert that class to a template
    >> class but I'm having trouble declaring the friend functions of that
    >> template class. Can anyone
    >> help? Any tip is more than welcomed.

    >
    > It's a bit tricky, but possible:
    >
    > //-------
    > template<class T> class foo {
    > public:
    > foo(T t): t(t) {}
    > protected:
    > T t;
    > template<class U> friend void inspect_foo(foo<U> f);
    > };
    >
    > template<class T> void inspect_foo(foo<T> f) {
    > cout << f.t << endl;
    > }
    > //-------
    >


    Well, no, the word I meant to use wasn't exactly "tricky" but more on
    the side of "verbose / tedious" - if you have lots of overloads it's way
    easier to put them in a class and make that a friend, just like
    suggested by Victor.

    I wonder what's the rationale of not allowing to simply say:

    friend function_name;

    and set all overloads of "function_name" as friends, regardless of their
    arguments or return types - I suppose the mechanism is not as simple as
    I'd expect it to be, with these words of mine.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
    Francesco S. Carta, Jul 12, 2010
    #4
  5. "Francesco S. Carta" <> writes:

    > Rui Maciel <>, on 12/07/2010 21:08:03, wrote:
    >
    >> I have a class which has a set of friend functions. Now I wish to
    >> convert that class to a template class but I'm having trouble
    >> declaring the friend functions of that template class. Can anyone
    >> help? Any tip is more than welcomed.

    >
    > It's a bit tricky, but possible:
    >
    > //-------
    > template<class T> class foo {
    > public:
    > foo(T t): t(t) {}
    > protected:
    > T t;
    > template<class U> friend void inspect_foo(foo<U> f);
    > };
    >
    > template<class T> void inspect_foo(foo<T> f) {
    > cout << f.t << endl;
    > }
    > //-------


    This is not an incorrect example, I do not think. However, note that
    parameterization of inspect_foo as a friend of class foo makes *all*
    specializations of inspect_foo a friend of any particular specialization
    of class foo, which seems a little arbitrary. If, on the other hand, we
    look at a similar example in which only inspect_foo<aType>(foo<aType>)
    is a friend of foo<aType>, then the requirements of declaring a function
    template a friend of a parameterized type begin to look a little less
    straight forward, as I believe the following would be required:

    #include <iostream>

    using namespace std;

    template<class T>
    class foo; // forward declaration of foo

    template<class T>
    void inspect_foo(foo<T>); // foward declaration of friend

    template<class T>
    class foo { // definition of foo
    public:
    foo(T t): t(t) { }
    protected:
    T t;
    friend void inspect_foo<>(foo<T> f);
    };

    template<class T>
    void inspect_foo(foo<T> f) { // definition of friend function
    cout << f.t << endl;
    }

    int main()
    {
    inspect_foo(foo<int>(1));
    }

    Regards

    Paul Bibbings
    Paul Bibbings, Jul 12, 2010
    #5
  6. Paul Bibbings <>, on 12/07/2010 22:25:09, wrote:

    > "Francesco S. Carta"<> writes:
    >
    >> Rui Maciel<>, on 12/07/2010 21:08:03, wrote:
    >>
    >>> I have a class which has a set of friend functions. Now I wish to
    >>> convert that class to a template class but I'm having trouble
    >>> declaring the friend functions of that template class. Can anyone
    >>> help? Any tip is more than welcomed.

    >>
    >> It's a bit tricky, but possible:
    >>
    >> //-------
    >> template<class T> class foo {
    >> public:
    >> foo(T t): t(t) {}
    >> protected:
    >> T t;
    >> template<class U> friend void inspect_foo(foo<U> f);
    >> };
    >>
    >> template<class T> void inspect_foo(foo<T> f) {
    >> cout<< f.t<< endl;
    >> }
    >> //-------

    >
    > This is not an incorrect example, I do not think. However, note that
    > parameterization of inspect_foo as a friend of class foo makes *all*
    > specializations of inspect_foo a friend of any particular specialization
    > of class foo, which seems a little arbitrary.


    I don't think that would be a problem: after all, there is no way to
    pass a "wrong" foo to inspect_foo.

    > If, on the other hand, we
    > look at a similar example in which only inspect_foo<aType>(foo<aType>)
    > is a friend of foo<aType>, then the requirements of declaring a function
    > template a friend of a parameterized type begin to look a little less
    > straight forward, as I believe the following would be required:
    >
    > #include<iostream>
    >
    > using namespace std;
    >
    > template<class T>
    > class foo; // forward declaration of foo
    >
    > template<class T>
    > void inspect_foo(foo<T>); // foward declaration of friend
    >
    > template<class T>
    > class foo { // definition of foo
    > public:
    > foo(T t): t(t) { }
    > protected:
    > T t;
    > friend void inspect_foo<>(foo<T> f);
    > };
    >
    > template<class T>
    > void inspect_foo(foo<T> f) { // definition of friend function
    > cout<< f.t<< endl;
    > }
    >
    > int main()
    > {
    > inspect_foo(foo<int>(1));
    > }


    As a further proof that C++ can really become tedious and verbose, at times.

    Luckily, we can declare friend classes and fly straight over all this
    awful machinery ;-)

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
    Francesco S. Carta, Jul 12, 2010
    #6
  7. Rui Maciel

    Rui Maciel Guest

    Victor Bazarov wrote:

    > class Boo { // has all instance of 'Foo' as friends
    > template<class T> friend class Foo;
    > };
    >
    > If that doesn't fit your needs, perhaps you need to be more specific
    > (and post some code this time).


    Thanks for the help, Victor. Nonetheless, instead of a friend class I was looking for a way to
    declare friend functions of a template class, like Francesco did.


    Thanks anyway,
    Rui Maciel
    Rui Maciel, Jul 12, 2010
    #7
  8. Rui Maciel

    Rui Maciel Guest

    Francesco S. Carta wrote:

    > It's a bit tricky, but possible:
    >
    > //-------
    > template<class T> class foo {
    > public:
    > foo(T t): t(t) {}
    > protected:
    > T t;
    > template<class U> friend void inspect_foo(foo<U> f);
    > };
    >
    > template<class T> void inspect_foo(foo<T> f) {
    > cout << f.t << endl;
    > }
    > //-------


    I've followed your suggestion and it appears that it works. I thought that the declaration of a
    template friend function would be something like:

    <code>

    template<class T> class foo {
    public:
    foo(T t): t(t) {}
    protected:
    T t;
    template<class T> friend void inspect_foo(foo<T> f);
    };

    template<class T> void inspect_foo(foo<T> f) {
    cout << f.t << endl;
    }

    </code>

    Is there a reason for that not to work?


    Rui Maciel
    Rui Maciel, Jul 12, 2010
    #8
  9. Rui Maciel <>, on 12/07/2010 23:41:05, wrote:

    > Francesco S. Carta wrote:
    >
    >> It's a bit tricky, but possible:
    >>
    >> //-------
    >> template<class T> class foo {
    >> public:
    >> foo(T t): t(t) {}
    >> protected:
    >> T t;
    >> template<class U> friend void inspect_foo(foo<U> f);
    >> };
    >>
    >> template<class T> void inspect_foo(foo<T> f) {
    >> cout<< f.t<< endl;
    >> }
    >> //-------

    >
    > I've followed your suggestion and it appears that it works. I thought that the declaration of a
    > template friend function would be something like:
    >
    > <code>
    >
    > template<class T> class foo {
    > public:
    > foo(T t): t(t) {}
    > protected:
    > T t;
    > template<class T> friend void inspect_foo(foo<T> f);
    > };
    >
    > template<class T> void inspect_foo(foo<T> f) {
    > cout<< f.t<< endl;
    > }
    >
    > </code>
    >
    > Is there a reason for that not to work?


    The above is reported as "shadowing" by my compiler, and, at the same
    time, it tells that it happens to be an error.

    I don't really know the rationale behind making such "shadowing" an
    error instead of (just) a warning.

    By the way, just for fiddling, I've made this test which sort of take
    advantage of NOT shadowing T (well, OK, I am not allowed to shadow it in
    any case, so no big "taking"):

    //-------
    #include <iostream>

    using namespace std;

    template<class T> class foo {
    public:
    foo(T t): t(t) {}
    T get_t() {
    return t;
    }
    private:
    T t;
    template<class U> friend void inspect(foo<U> f, T t);
    };

    template<class W> void inspect(foo<W> f, int i) {
    // accesses the private interface
    cout << f.t << endl;
    cout << i << endl;
    }

    template<class W> void inspect(foo<W> f, double d) {
    // accesses the private interface
    cout << f.t << endl;
    cout << d << endl;
    }

    template<class W> void inspect(foo<W> f, const char* cstr) {
    // accesses only the public interface
    cout << f.get_t() << endl;
    cout << cstr << endl;
    }

    int main() {
    foo<int> i(42);
    foo<double> d(4.2);

    // (int, int) compiles as a friend
    inspect(i, 78);

    // (double, double) compiles as a friend
    inspect(d, 7.8);

    // (not an int, int) error: not a friend!
    //inspect(d, 78);

    // (not a double, double) error: not a friend!
    //inspect(i, 7.8);

    // (whatever, const char*) compiles - not a friend, no need to
    inspect(i, "int");
    inspect(d, "double");

    return 0;
    }
    //-------


    In the above code only the "inspect" instantiations whose second
    parameter's type matches the (inspect's) template type are allowed to
    access the "innards" of "foo" (whatever its type), all the others can
    only access its public interface.

    I'm not able to see any immediate use of this - although I think someone
    must have used something like this, somewhere.

    The point could be: to do the above I've "had" to use the name "T" in
    the declaration of "inspect", within of "foo".

    Had I used "T" as "inspect" template parameter (shadowing "foo"'s
    template parameter) that trick would have been impossible.

    And with "trick" I mean "declaring, with a single line, a friend
    function that is a /true friend/ only when its parameters equate each other"

    Still, that's not enough of a reason to forbid shadowing.

    I'm not so sure I could be able to understand all that I wrote here above.

    That could be my English' fault. That could be the late hour's fault.
    That could well be the templates' fault - or my understanding of them,
    more likely ;-)

    Templates: lovely, tricky bastards. Good night.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
    Francesco S. Carta, Jul 13, 2010
    #9
  10. Rui Maciel wrote:
    > Francesco S. Carta wrote:
    >
    >> It's a bit tricky, but possible:
    >>
    >> //-------
    >> template<class T> class foo {
    >> public:
    >> foo(T t): t(t) {}
    >> protected:
    >> T t;
    >> template<class U> friend void inspect_foo(foo<U> f);
    >> };
    >>
    >> template<class T> void inspect_foo(foo<T> f) {
    >> cout << f.t << endl;
    >> }
    >> //-------

    >
    > I've followed your suggestion and it appears that it works. I thought that the declaration of a
    > template friend function would be something like:
    >
    > <code>
    >
    > template<class T> class foo {
    > public:
    > foo(T t): t(t) {}
    > protected:
    > T t;
    > template<class T> friend void inspect_foo(foo<T> f);
    > };
    >
    > template<class T> void inspect_foo(foo<T> f) {
    > cout << f.t << endl;
    > }
    >
    > </code>
    >
    > Is there a reason for that not to work?


    1) you are missing main() and includes
    2) When you fix 1, then you should get a compiler complaining about
    shadowing a template parameter. The problem is, you are declaring two
    class types with the same name T, and that is not allowed. How would the
    compiler differentiate two?

    Maybe you wanted something like this :


    #include <iostream>
    using namespace std;
    template<class T> class foo {
    public:
    foo(T t): t(t) {}
    protected:
    T t;
    inline friend void inspect_foo( const foo< T > &f )
    {
    cout << f.t << endl;
    }
    };

    int main()
    {
    foo< int > a(5);
    inspect_foo(a);
    }

    But see what Paul Bibbings wrote in other tread.
    Vladimir Jovic, Jul 13, 2010
    #10
  11. Rui Maciel

    Bo Persson Guest

    Francesco S. Carta wrote:
    > Francesco S. Carta <>, on 12/07/2010 22:29:59,
    > wrote:
    >> Rui Maciel <>, on 12/07/2010 21:08:03, wrote:
    >>
    >>> I have a class which has a set of friend functions. Now I wish to
    >>> convert that class to a template
    >>> class but I'm having trouble declaring the friend functions of
    >>> that template class. Can anyone
    >>> help? Any tip is more than welcomed.

    >>
    >> It's a bit tricky, but possible:
    >>
    >> //-------
    >> template<class T> class foo {
    >> public:
    >> foo(T t): t(t) {}
    >> protected:
    >> T t;
    >> template<class U> friend void inspect_foo(foo<U> f);
    >> };
    >>
    >> template<class T> void inspect_foo(foo<T> f) {
    >> cout << f.t << endl;
    >> }
    >> //-------
    >>

    >
    > Well, no, the word I meant to use wasn't exactly "tricky" but more
    > on the side of "verbose / tedious" - if you have lots of overloads
    > it's way easier to put them in a class and make that a friend, just
    > like suggested by Victor.
    >
    > I wonder what's the rationale of not allowing to simply say:
    >
    > friend function_name;
    >
    > and set all overloads of "function_name" as friends, regardless of
    > their arguments or return types - I suppose the mechanism is not as
    > simple as I'd expect it to be, with these words of mine.


    That would let anyone write additional unrelated overloads, and get
    access to the private class members. Could as well make them public.


    Bo Persson
    Bo Persson, Jul 13, 2010
    #11
  12. Bo Persson <>, on 13/07/2010 19:48:45, wrote:

    > Francesco S. Carta wrote:
    >> Francesco S. Carta<>, on 12/07/2010 22:29:59,
    >> wrote:
    >>> Rui Maciel<>, on 12/07/2010 21:08:03, wrote:
    >>>
    >>>> I have a class which has a set of friend functions. Now I wish to
    >>>> convert that class to a template
    >>>> class but I'm having trouble declaring the friend functions of
    >>>> that template class. Can anyone
    >>>> help? Any tip is more than welcomed.
    >>>
    >>> It's a bit tricky, but possible:
    >>>
    >>> //-------
    >>> template<class T> class foo {
    >>> public:
    >>> foo(T t): t(t) {}
    >>> protected:
    >>> T t;
    >>> template<class U> friend void inspect_foo(foo<U> f);
    >>> };
    >>>
    >>> template<class T> void inspect_foo(foo<T> f) {
    >>> cout<< f.t<< endl;
    >>> }
    >>> //-------
    >>>

    >>
    >> Well, no, the word I meant to use wasn't exactly "tricky" but more
    >> on the side of "verbose / tedious" - if you have lots of overloads
    >> it's way easier to put them in a class and make that a friend, just
    >> like suggested by Victor.
    >>
    >> I wonder what's the rationale of not allowing to simply say:
    >>
    >> friend function_name;
    >>
    >> and set all overloads of "function_name" as friends, regardless of
    >> their arguments or return types - I suppose the mechanism is not as
    >> simple as I'd expect it to be, with these words of mine.

    >
    > That would let anyone write additional unrelated overloads, and get
    > access to the private class members. Could as well make them public.


    Yes, that's a good reason - a good reason to avoid using it, but maybe
    not a good reason to completely forbid it... although I must admit that
    having such a feature could lead lazy programmers to abuse it instead of
    declaring specifically targeted friend functions... yes, after all, I
    think it's better not to have it.

    Thanks for pointing that out, I didn't think about it even though that
    rationale looks pretty obvious now.

    --
    FSC - http://userscripts.org/scripts/show/59948
    http://fscode.altervista.org - http://sardinias.com
    Francesco S. Carta, Jul 13, 2010
    #12
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    1
    Views:
    1,307
    Jim Langston
    Nov 9, 2006
  2. =?gb2312?B?wfXquw==?=
    Replies:
    10
    Views:
    685
    Victor Bazarov
    Aug 1, 2007
  3. Replies:
    2
    Views:
    655
    Triple-DES
    Feb 26, 2008
  4. slocum
    Replies:
    4
    Views:
    1,379
    Martin York
    Apr 10, 2008
  5. A L
    Replies:
    1
    Views:
    504
    Alf P. Steinbach /Usenet
    Aug 25, 2010
Loading...

Share This Page