0

Given the following situation:

template<typename T>
class Foo
{
private:
    Foo(/*args*/);

public:
    static Foo<T> create(/*args*/);

    template<typename U>
    Foo<U> bar(/*args*/);
};

I have this create function for users of this class to use instead of its constructor. The bar function needs to instantiate a Foo but with a different template type. This bar function can't use create because its arguments are not suited for it. This doesn't compile because, AFAIU, Foo<T> and Foo<U> are plainly different types and they can't see each other's private functions just like any two unrelated classes can't.

I've resorted to having the constructor public but is there a way out given the goal of enforcing instantiation through the create function exclusively by users of this class?

Edit: minimal reproducible example and compiler's output:

template<typename T>
class Foo
{
private:
    Foo(/*args*/)
    {}

public:
    static Foo<T> create(/*args*/)
    {
        return Foo<T>();
    }

    template<typename U>
    Foo<U> bar(/*args*/)
    {
        return Foo<U>();
    }
};

int main()
{
    auto fi = Foo<int>::create();
    auto ff = fi.bar<float>();
    (void)ff;

    return 0;
}

main.cpp:17:16: error: calling a private constructor of class 'Foo<float>'
        return Foo<U>();
               ^
main.cpp:24:18: note: in instantiation of function template specialization 'Foo<int>::bar<float>' requested here
    auto ff = fi.bar<float>();
                 ^
main.cpp:5:5: note: declared private here
    Foo(/*args*/)
screwnut
  • 1,367
  • 7
  • 26
  • "This doesn't compile because," .... does it not? Please post a [mcve] and the compiler error message. One can guess what the problem is, but it isnt present in the code you posted – 463035818_is_not_an_ai Oct 27 '21 at 11:59
  • In case anyone comes here and incorrectly concludes that the answer is "no" by going to the first duplicate. The answer is actually found [here](https://stackoverflow.com/questions/26147061/how-to-share-protected-members-between-c-template-classes) and, in the context of my question, the answer is to friend `Foo` like so `template friend class Foo;`. When you do that, the constructor can be kept private because you've now friended all possible `Foo<>` types. – screwnut Oct 27 '21 at 12:19
  • the answer in the first duplicate has `template friend class A;` to make any `A` a friend of `A` as well. Nobody said that it isnt possible – 463035818_is_not_an_ai Oct 28 '21 at 09:12

0 Answers0