【问题标题】:Template default arguments模板默认参数
【发布时间】:2013-02-28 17:01:45
【问题描述】:

如果允许我执行以下操作:

template <typename T = int>
class Foo{
};

为什么我不能在 main 中执行以下操作?

Foo me;

但我必须指定以下内容:

Foo<int> me;

C++11 引入了默认模板参数,现在我无法完全理解它们。

【问题讨论】:

    标签: c++ templates


    【解决方案1】:

    注意:

    Foo me; 没有模板参数在 C++17 中是合法的。看到这个答案:https://stackoverflow.com/a/50970942/539997

    适用于 C++17 之前的原始答案:

    你必须这样做:

    Foo<> me;
    

    模板参数必须存在,但您可以将它们留空。

    把它想象成一个带有单个默认参数的函数foo。表达式foo 不会调用它,但foo() 会。参数语法必须仍然存在。这与那是一致的。

    【讨论】:

    • @Pubby 我想如果Foo 可能是一个模板标识符或可能是一个明确的实例化,这取决于是否有一个默认参数。更好地保留显式实例化语法。把它想象成一个带有单个默认参数的函数foo。你不能像foo 这样称呼它,你可以用foo() 称呼它。保持这种一致性是有意义的。
    • @sftrabbit 但你也不能调用像foo 这样没有参数的函数;但是,您可以将不带参数的类命名为 Foo
    • @aschepler 使用函数,可以从函数参数中推导出模板参数。对于类,无法决定您是指具有默认参数的模板类还是非模板类。
    • @OlafDietsche 但是你不能有同名的模板类和非模板类,所以编译器应该能够通过查看名称来决定。
    • @Pubby 我猜标准委员会也这样问自己。现在,使用 C++17,&lt;&gt; 在这种情况下不再需要。查看我的回答了解更多详情。
    【解决方案2】:

    使用 C++17,确实可以。

    此功能称为class template argument deduction,它为您声明模板类型的变量的方式增加了更多灵活性。

    所以,

    template <typename T = int>
    class Foo{};
    
    int main() {
        Foo f;
    }
    

    现在是legal C++ code

    【讨论】:

    • 奇怪。刚刚在我的 C++17 项目中尝试过,它不起作用:“模板占位符类型‘const MyType’必须后跟一个简单的 declarator-id”。我正在使用 GCC 7.3.0。
    • @Silicomancer 没有看到你的代码和命令行很难说...也许你在处理指针like here
    • @PaoloM 哦酷,很高兴知道这只是一个编译器版本问题。感谢您对此进行调查。
    • 这应该是最佳答案 - 最佳答案已过时。
    【解决方案3】:

    你不能这样做,但你可以这样做

    typedef Foo<> Fooo;
    

    然后做

    Fooo me;
    

    【讨论】:

    • 这个有默认类型和:typedef Foo&lt;float&gt; Fooo;,没有默认类型有什么区别吗?
    • C++11 风格的方式是说using Fooo = Foo&lt;&gt;;
    【解决方案4】:

    您可以使用以下内容:

    Foo<> me;
    

    并让int 成为您的模板参数。尖括号是必须的,不能省略。

    【讨论】:

    • 有道理,谢谢,但是,如下所述,为什么指定的类型不存在?
    • @user633658:您的意思是“类型说明符”吗?我不确定我是否理解
    • 无论如何,关于需要空尖括号背后的原因,我只能做出推测,它们都是为了排除单独使用模板名称可能产生的歧义,但我必须承认我不知道确切的原因
    • 我强烈怀疑对 的要求是让编译器的解析器能够确定您指的是一个名为 foo 的模板类,而不是其他名为 foo 的东西。
    【解决方案5】:

    根据C++17 标准,必须传递模板参数。

    但如果您仍然想解决这个问题,请像这样使用#define

    template <typename T>
    class Foo{
    };
    
    #define IFoo Foo<int>
    

    快速提醒

    预处理器不利于调试。

    【讨论】:

    • 这显然比using IFoo=Foo&lt;int&gt; 更糟糕。宏的忽略命名空间
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多