Rsevero
Rsevero

Reputation: 330

How can I make a typedef or alias for a template function that can also be used in friend function declarations?

If I have something like this:

mytemplates.h

#ifndef MYTEMPLATES_H
#define MYTEMPLATES_H

#include <iostream>
#include <memory>
#include <string>

class BaseClass;
// Alias (non-working) version:
//class DerivedClass1;

namespace MyTemplates
{
    typedef std::unique_ptr<BaseClass> object_up;
    
    template<typename SomeDerivedClass>
    object_up createFromIntFloat(int intParam, float floatParam)
    {
        SomeDerivedClass *newObject_raw = new SomeDerivedClass(intParam, floatParam);

        object_up uniqueObject {newObject_raw};

        std::cout << "createFromIntFloat." << "\n";

        return uniqueObject;
    }
    // Alias (non-working) version:
    //using createFromIntFloatPtrType = object_up(*)(int intParam, float floatParam);

    template<typename SomeDerivedClass>
    object_up createFromString(std::string stringParam)
    {
        SomeDerivedClass *newObject_raw = new SomeDerivedClass(stringParam);

        object_up uniqueObject {newObject_raw};

        std::cout << "createFromString." << "\n";

        return uniqueObject;
    }
    // Alias (non-working) version:
    //using createFromStringPtrType = object_up(*)(std::string stringParam);  

    // Alias (non-working) version:
    // createFromStringPtrType createDerivedClass1 =  createFromString<DerivedClass1>;
}

#endif // MYTEMPLATES_H

baseclass.h

#ifndef BASECLASS_H
#define BASECLASS_H

class BaseClass
{
protected:
    BaseClass(){};
};

#endif // BASECLASS_H

derivedclass1.h

#ifndef DERIVEDCLASS1_H
#define DERIVEDCLASS1_H

#include "baseclass.h"
#include "mytemplates.h"

class DerivedClass1 : public BaseClass
{
    std::string stringParam;
protected:
    DerivedClass1(std::string aStringParam) : BaseClass(), stringParam(aStringParam) {};

    // Alias (non-working) version:
    // friend MyTemplates::object_up MyTemplates::createDerivedClass1(std::string stringParam);

    // Non-alias version:
    friend MyTemplates::object_up MyTemplates::createFromString<DerivedClass1>(std::string stringParam);
};

#endif // DERIVEDCLASS1_H

main.cpp

#include "mytemplates.h"
#include "derivedclass1.h"

int main(int argc, char *argv[])
{
    // Alias (non-working) version:
    // MyTemplates::object_up uniqueClass1 = MyTemplates::createDerivedClass1("creation info for class 1");
    
    // Non-alias version:
    MyTemplates::object_up uniqueClass1 = MyTemplates::createFromString<DerivedClass1>("creation info for class 1");
}

I would like to create some kind of alias like the Alias (non-working) version on the above code so that I could use this alias - createDerivedClass1 - both in direct calling like in main.cpp and in friend declarations like in derivedclass1.h

How can I change the code above from the Non-alias version to the Alias version and make it work?

Upvotes: 0

Views: 75

Answers (1)

Serge Ballesta
Serge Ballesta

Reputation: 149125

Aliases are for types because types are not first class objects in C++. But you do not need aliases for plain functions because you can simply use function pointers.

But a function pointer is just a pointer and you must declare the real function to be friend. It all boil down to:

...
class DerivedClass1 : public BaseClass
{
    std::string stringParam;
protected:
    DerivedClass1(std::string aStringParam) : BaseClass(), stringParam(aStringParam) {};

    // Alias (non-working) version:
    //friend MyTemplates::object_up MyTemplates::createDerivedClass1(std::string stringParam);

    // Non-alias version:
    friend MyTemplates::object_up MyTemplates::createFromString<DerivedClass1>(std::string stringParam);
};

namespace MyTemplates {
    object_up(*createDerivedClass1)(std::string) = createFromString<DerivedClass1>;
}

int main(int argc, char* argv[])
{
    // Alias (non-working) version:
    MyTemplates::object_up uniqueClass1 = MyTemplates::createDerivedClass1("creation info for class 1");

    // Non-alias version:
    MyTemplates::object_up uniqueClass2 = MyTemplates::createFromString<DerivedClass1>("creation info for class 1");
}

Upvotes: 1

Related Questions