【问题标题】:Class constructor with non-argument template type具有非参数模板类型的类构造函数
【发布时间】:2009-09-19 02:36:11
【问题描述】:

对于普通的 C++ 函数,模板参数可能不会出现在参数列表中:

template<typename T>
T default_construct()
{
    return T();
}

并调用它

some_type x = default_construct<some_type>();

即使我使用的类型不在参数列表中,我仍然可以将它传递给函数。现在,我想在类构造函数中执行此操作:

struct Base;

template<typename T>
Base* allocate()
{
    return new T; //Assume T derives from Base...
}

struct factory {
    template<typename T>
    factory()
        : func(allocate<T>)
    {}

    std::tr1::function<Base*()> func;
};

但是当我想构造factory 的实例时,我找不到将参数提供给构造函数的方法。

有没有办法做到这一点不将类转换为模板类或将一些未使用的T 对象发送给构造函数?

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    不,没有办法做到这一点。标准中14.8.1/5 的注释解释了原因

    [注意:因为显式模板实参列表跟在函数模板名之后,并且因为转换成员函数模板和构造函数成员函数模板是在不使用函数名的情况下调用的,所以没有办法为这些提供显式模板实参列表功能模板。 ]

    当然,它不需要是您发送的T 对象。它可以是在其类型中编码有T 的任何对象

    template<typename T> struct type2type { };
    
    struct factory {
        template<typename T>
        factory(type2type<T>)
            : func(allocate<T>)
        {}
    
        std::tr1::function<Base*()> func;
    };
    
    factory f((type2type<Foo>()));
    

    【讨论】:

    • 好吧,标准答案中的引用非常清楚。谢谢。
    【解决方案2】:

    不,你不能。使用“类型标签对象”调用给定类型的未使用对象。您可以创建每种类型的全局变量,也可以每次都使用默认构造函数。

    您可以合理地希望,如果内联构造函数,则永远不会真正创建类型标记。

    【讨论】:

      【解决方案3】:

      litb 和 wrang-wrang 的回答很好。作为另一种可能性,您可以考虑将所有(非复制)构造函数声明为私有或受保护,并创建一个或多个静态成员函数模板factory create&lt;T&gt;()。然后,定义一个工厂实例,而不是

      factory<SomeType> f;                      // 1 (doesn't compile)
      

      你会写

      factory f(factory::create<SomeType>());   // 2
      

      显然不如 (1) 漂亮,但恕我直言,比使用类型标签更清晰。 (编译器会在实践中消除副本。)

      顺便说一句,您是否有理由不能简单地将factory 设为类模板?然后(1)中的语法将编译。 (这意味着不同类型的工厂不能相互分配。)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2016-06-01
        • 2013-08-26
        • 2018-05-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-16
        • 1970-01-01
        相关资源
        最近更新 更多