【问题标题】:How can I make a typedef or alias for a template function that can also be used in friend function declarations?如何为也可以在友元函数声明中使用的模板函数创建 typedef 或别名?
【发布时间】:2022-02-01 15:10:21
【问题描述】:

如果我有这样的事情:

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

基类.h

#ifndef BASECLASS_H
#define BASECLASS_H

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

#endif // BASECLASS_H

派生类1.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");
}

我想在上述代码上创建某种别名,例如 Alias(非工作)版本,以便我可以使用此别名 - createDerivedClass1 - 两者在 main.cpp 中的直接调用和 derivedclass1.h

中的友元声明中

如何将上面的代码从非别名版本更改为别名版本并使其工作?

【问题讨论】:

  • createDerivedClass1 是一个函数指针,所以friend 声明是错误且无用的。所以你的全局变量应该只定义一次(或者是inline)。
  • @Jarod42 那么如何让 createFromString 访问 DerivedClass1 受保护的 ctor?
  • @Jarod42 哦,我相信我现在看到了:我保留了朋友声明的原始(非别名版本)并在其他地方使用别名版本,对吧?
  • createDerivedClass1(可能是const/constexpr)只是“调用”createFromString&lt;DerivedClass1&gt;,所以不需要额外的访问权限。您可以取消注释除朋友声明之外的所有内容。 (并为您的全局修复 ODR)。

标签: c++ templates friend


【解决方案1】:

别名用于类型,因为类型不是 C++ 中的第一类对象。但是你不需要普通函数的别名,因为你可以简单地使用函数指针。

但是函数指针只是一个指针,你必须将真正的函数声明为友元。这一切都归结为:

...
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");
}

【讨论】:

  • 此解决方案在我的示例代码中完美运行,但当我尝试将此解决方案转换为我的真实代码时,我收到“不完整类型'DerivedClass1''的分配”等效错误消息。我只有在使用别名时才得到它。使用非别名版本,它工作正常。有任何想法吗?不幸的是,我无法通过最后一个错误生成代码的简化版本。
  • @Rsevero:这里我只在DerivedClass1 的定义之后声明并使用了指向func 的指针,并没有尝试在该定义中使用它。任何以不同方式使用它的尝试都会引发类似于您描述的错误。
  • 我将指针 func 的声明移至 MyTemplates.cpp 并且效果很好。谢谢!
猜你喜欢
  • 2019-06-10
  • 2013-09-18
  • 2016-02-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多