-2

I'm working on a piece of code that looks like this:

template<typename T>
class A {
    // makeA should become a friend
    A() {}
};

template<typename T, typename U>
A<T> makeA(const U & u) {
    (void) u;
    return A<T>();
}

int main() {
    makeA<double>(3);
    return 0;
}

But I cannot let makeA become a friend of A. Is this possible? What is the right syntax?

DarioP
  • 5,377
  • 1
  • 33
  • 52
  • first you shouldn't make A() -->constructor private – Ankur Jan 05 '15 at 17:19
  • What *"right syntax"* are you asking? that makes `makeA` a friend? What exactly is your question? You want to make it friend? Or without making it friend, you want to access the private constructor? – Nawaz Jan 05 '15 at 17:21
  • @Nawaz the answer you posted was what I was looking for. In the friendship declaration I was using `makeA(U)` instead of `makeA(const U &)`. Thanks! – DarioP Jan 05 '15 at 17:25
  • @Nawaz can I access the private constructor without making it friend??? – DarioP Jan 05 '15 at 17:26
  • @DarioP: Okay, I undeleted by answer if that is what you're looking for. And no, `makeA` cannot access the private constructor if it isn't a friend (if that was possible and good enough, then the language wouldn't have `friend` feature). – Nawaz Jan 05 '15 at 17:29
  • 1
    @Shan Uhm what please? That's probably the reason why one want's to have a `friend` function for construction?! – πάντα ῥεῖ Jan 05 '15 at 17:37

4 Answers4

1

You could make it friend as:

template<typename T>
class A
{

   template<typename TT, typename U>
   friend A<TT> makeA(const U & u) ;

};

You could even define the friend function inside the class.

Nawaz
  • 353,942
  • 115
  • 666
  • 851
1

While the solution

template <typename T>
class A
{

   template<typename TT, typename U>
   friend A<TT> makeA(const U & u) ;

};

works, it suffers from the side effect that makeA<int, int> is a friend of not only A<int> but also a friend of A<double>, A<char>, etc. In other workds, makeA<TT, U> is a friend of every A<T>. The friendship granted by A<T> is too broad.

You can limit that by using a different design.

template <typename T> class AMaker;

template <typename T>
class A
{
   A() {}

   friend class AMaker<T>;
};

template<typename T> class AMaker
{
   public:
      template <typename U>
         static A<T> make(const U & u)
         {
            (void) u;
            return A<T>();
         }
};

int main()
{
   A<double> x = AMaker<double>::make(3);
   return 0;
}

Here, friendship granted by A<T> is limited to only AMaker<T>. AMaker<int> is friend of A<int> but not of A<double>.

R Sahu
  • 204,454
  • 14
  • 159
  • 270
0

I have done some changes in your program template

class A {
    // makeA should become a friend

    A() {} 
    public:
    template<typename S,typename U>
    friend A<S> makeA(const U & u); //this is correct way to makeA friend of A
};

template<typename T, typename U>
A<T> makeA(const U & u) {
    (void) u;
    return A<T>();
}

int main() {
  makeA<double>(3);
    return 0;
}

Now it will work as you can see here http://ideone.com/1F1l3o

Ankur
  • 3,584
  • 1
  • 24
  • 32
0

Here is a solution that does not use friend:

template<class T>
class A {
    A() {}
public:
    template<class U> static A make(U && u) {
        return A();
    }
};

template<class T, class U>
A<T> makeA(U && u) {
    return A<T>::template make<U>(std::forward<U>(u));
}
Fozi
  • 4,973
  • 1
  • 32
  • 56