【问题标题】:Implicit Template Parameters隐式模板参数
【发布时间】:2011-02-09 16:00:19
【问题描述】:

以下代码在 Xcode 中生成编译错误:

template <typename T>
struct Foo
{
    Foo(T Value)
    {
    }
};

int main()
{
    Foo MyFoo(123);
    return 0;
}

error: missing template arguments before 'MyFoo'

Foo MyFoo(123); 更改为Foo&lt;int&gt; MyFoo(123); 可以解决问题,但编译器不应该能够找出适当的数据类型吗?

这是编译器的错误,还是我误解了隐式模板参数?

【问题讨论】:

    标签: c++ xcode templates implicit


    【解决方案1】:

    构造函数理论上可以推断出它正在构造的对象的类型,但是语句:

    Foo MyFoo(123);
    

    正在为MyFoo 分配临时空间,并且必须知道MyFoo 的完全限定类型才能知道需要多少空间。

    如果您想避免输入(即用手指)特别复杂的模板名称,请考虑使用typedef

    typedef std::map<int, std::string> StringMap;
    

    或者在 C++0x 中,您可以使用 auto 关键字让编译器使用类型推断——尽管许多人会认为这会导致代码可读性降低且更容易出错,我就是其中之一。 ;p

    【讨论】:

    • 如果它可以推断类型,它可以推断空间。
    • 它可以推断构造函数调用的类型,但不能推断存储空间。如果你将一个变量简单地定义为Foo,它是否可以同时包含Foo&lt;int&gt;Foo&lt;std::string&gt;?还是它总是知道自己内心深处是一个Foo&lt;int&gt;?如果变量是const,那么它可以被实现,因为值不能被重新分配,但是对于const TT,我们会有不同的词法规则,并且会产生巨大的破坏。
    • “打字(即用手指)”是一个宝石:D
    【解决方案2】:

    编译器只能为模板化函数确定模板参数类型,而不是类/结构

    【讨论】:

    • 毕竟,函数std::make_pair&lt;typename T, typename U&gt;(T t, U u)是有原因的,尽管我们已经有了std::pair&lt;typename T, typename U&gt;这个类。
    【解决方案3】:

    编译器可以推导出模板参数这样的情况:

    template<typename T>
    void fun(T param)
    {
        //code...
    }
    
    fun(100);    //T is deduced as int;
    fun(100.0);  //T is deduced as double
    fun(100.0f); //T is deduced as float
    
    Foo<int> foo(100);
    fun(foo);    //T is deduced as Foo<int>;
    
    Foo<char> bar('A');
    fun(bar);    //T is deduced as Foo<char>;
    

    其实模板参数推导是一个很大的话题。在 ACCU 阅读这篇文章:

    The C++ Template Argument Deduction

    【讨论】:

      【解决方案4】:

      在 C++11 中你可以使用decltype:

      int myint = 123;
      Foo<decltype(myint)> MyFoo(myint);
      

      【讨论】:

        【解决方案5】:

        这不是错误,它是不存在的功能。您必须在实例化期间完全指定类/结构模板参数,始终不会像函数模板那样推断类型。

        【讨论】:

          【解决方案6】:

          您现在尝试执行的操作在 C++ 17 中有效。模板参数可以在 C++ 17 中推断。

          template <typename T>
          struct Foo
          {
              Foo(T Value)
              {
              }
          };
          
          int main()
          {
              Foo a(123);
              Foo b = 123;
              Foo c {123};
              return 0;
          }
          

          【讨论】:

            【解决方案7】:

            这样很有意义,因为 Foo 不是一个类,只有 Foo&lt;T&gt; 其中 T 是一个类型。

            在 C++0x 中你可以使用 auto,你可以创建一个函数来让你成为 Foo,我们称之为 foo(小写 f)。然后你会做

            template<typename T> Foo<T> foo(int x)
            {
              return Foo<T>(x);
            }
            
            auto myFoo = foo(55);
            

            【讨论】:

            • 也许你的意思是:“template Foo foo(T x)”?
            猜你喜欢
            • 1970-01-01
            • 2011-08-24
            • 1970-01-01
            • 2016-10-26
            • 2017-05-09
            • 1970-01-01
            • 1970-01-01
            • 2016-05-22
            • 1970-01-01
            相关资源
            最近更新 更多