草庐IT

c++ - 为什么不会在函数调用中将模板形参包推导出为多个类型实参?

coder 2023-05-31 原文

我有一个在类型参数和参数包上模板化的类,我对这种类型的类型推导感到困惑;在编写输出流操作符时,我在 operator<< 上发现了一个参数包将不匹配模板类的 type 和 pack 参数:

#include <iostream>

template<class T, class... Ts>
struct foo
{ /* ... */ };

template< class... Ts >
std::ostream& operator<<( std::ostream& os, const foo<Ts...>& )
{
  return os << 42;
}


int main()
{
  std::cout << foo<int>();
}

这在 gcc-4.7.2 和 clang-3.0 上都无法编译,所以我想我在这里误解了规则。

gcc 说(其中第 16 行是输出流调用):

t.cpp:16:28: error: cannot bind ‘std::ostream {aka std::basic_ostream<char>}’ lvalue to ‘std::basic_ostream<char>&&’
In file included from /usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/iostream:40:0,
                 from t.cpp:1:
/usr/lib/gcc/x86_64-redhat-linux/4.7.2/../../../../include/c++/4.7.2/ostream:600:5: error:   initializing argument 1 of ‘std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&&, const _Tp&) [with _CharT = char; _Traits = std::char_traits<char>; _Tp = foo<int>]’

clang 说:

t.cpp:16:16: error: invalid operands to binary expression ('ostream' (aka 'basic_ostream<char>') and 'foo<int>')
        std::cout << foo<int>();
        ~~~~~~~~~ ^  ~~~~~~~~~~

[--- snip: lots of non-viable candidates from standard library ---]

t.cpp:8:19: note: candidate template ignored: substitution failure [with Ts = <>]
    std::ostream& operator<<( std::ostream& os, const foo<Ts...>& )
                  ^

谁能告诉我为什么 operator<< 的参数包不能推论为foo的类型参数参数包?

最佳答案

发生的情况是带有模板参数包的模板函数class... Ts , 参数类型 (P) 为 foo<Ts...>正在根据 foo<int> 的参数类型 (A) 进行推断.

14.8.2.5/9 这么说:

If P has a form that contains <T> or <i> [it does], then each argument Pi [Ts...] of the respective template argument list P is compared with the corresponding argument Ai [int] of the corresponding template argument list of A. If the template argument list of P contains a pack expansion that is not the last template argument, the entire template argument list is a non-deduced context. [the pack expansion is last, so the previous doesnt apply] If Pi is a pack expansion [Ts..., it is], then the pattern of Pi is compared with each remaining argument in the template argument list of A (int). Each comparison deduces template arguments for subsequent positions in the template parameter packs expanded by Pi.

所以 class... Ts应该推导出为一个元素列表int ,因此函数模板应使用参数类型 const foo<int>& 进行实例化,并且是可行的。

这是一个编译器错误。您的代码格式正确。

更简洁地说,这是格式良好的:

template<class A, class... B> struct S { };

template<class... C> void f(S<C...>) { }

int main() { f(S<int>()); }

但至少在 gcc 4.7.2 上同样失败:

 error: parameter 1 of ‘void f(S<C ...>) [with C = {int, C}]’
        has incomplete type ‘S<int, C>’

C被错误地推断为 C = {int, C} (无意义的递归)而不是 C = {int} . C的破扣导致更多的垃圾 S<int, C>类型不完整。

关于c++ - 为什么不会在函数调用中将模板形参包推导出为多个类型实参?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17277487/

有关c++ - 为什么不会在函数调用中将模板形参包推导出为多个类型实参?的更多相关文章

  1. ruby - 为什么我可以在 Ruby 中使用 Object#send 访问私有(private)/ protected 方法? - 2

    类classAprivatedeffooputs:fooendpublicdefbarputs:barendprivatedefzimputs:zimendprotecteddefdibputs:dibendendA的实例a=A.new测试a.foorescueputs:faila.barrescueputs:faila.zimrescueputs:faila.dibrescueputs:faila.gazrescueputs:fail测试输出failbarfailfailfail.发送测试[:foo,:bar,:zim,:dib,:gaz].each{|m|a.send(m)resc

  2. ruby-on-rails - 在 Rails 中将文件大小字符串转换为等效千字节 - 2

    我的目标是转换表单输入,例如“100兆字节”或“1GB”,并将其转换为我可以存储在数据库中的文件大小(以千字节为单位)。目前,我有这个:defquota_convert@regex=/([0-9]+)(.*)s/@sizes=%w{kilobytemegabytegigabyte}m=self.quota.match(@regex)if@sizes.include?m[2]eval("self.quota=#{m[1]}.#{m[2]}")endend这有效,但前提是输入是倍数(“gigabytes”,而不是“gigabyte”)并且由于使用了eval看起来疯狂不安全。所以,功能正常,

  3. ruby - 为什么 4.1%2 使用 Ruby 返回 0.0999999999999996?但是 4.2%2==0.2 - 2

    为什么4.1%2返回0.0999999999999996?但是4.2%2==0.2。 最佳答案 参见此处:WhatEveryProgrammerShouldKnowAboutFloating-PointArithmetic实数是无限的。计算机使用的位数有限(今天是32位、64位)。因此计算机进行的浮点运算不能代表所有的实数。0.1是这些数字之一。请注意,这不是与Ruby相关的问题,而是与所有编程语言相关的问题,因为它来自计算机表示实数的方式。 关于ruby-为什么4.1%2使用Ruby返

  4. ruby - Highline 询问方法不会使用同一行 - 2

    设置:狂欢ruby1.9.2高线(1.6.13)描述:我已经相当习惯在其他一些项目中使用highline,但已经有几个月没有使用它了。现在,在Ruby1.9.2上全新安装时,它似乎不允许在同一行回答提示。所以以前我会看到类似的东西:require"highline/import"ask"Whatisyourfavoritecolor?"并得到:Whatisyourfavoritecolor?|现在我看到类似的东西:Whatisyourfavoritecolor?|竖线(|)符号是我的终端光标。知道为什么会发生这种变化吗? 最佳答案

  5. ruby-on-rails - 如何优雅地重启 thin + nginx? - 2

    我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server

  6. ruby - 在没有 sass 引擎的情况下使用 sass 颜色函数 - 2

    我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re

  7. ruby-on-rails - 项目升级后 Pow 不会更改 ruby​​ 版本 - 2

    我在我的Rails项目中使用Pow和powifygem。现在我尝试升级我的ruby​​版本(从1.9.3到2.0.0,我使用RVM)当我切换ruby​​版本、安装所有gem依赖项时,我通过运行railss并访问localhost:3000确保该应用程序正常运行以前,我通过使用pow访问http://my_app.dev来浏览我的应用程序。升级后,由于错误Bundler::RubyVersionMismatch:YourRubyversionis1.9.3,butyourGemfilespecified2.0.0,此url不起作用我尝试过的:重新创建pow应用程序重启pow服务器更新战俘

  8. ruby-on-rails - 如果 Object::try 被发送到一个 nil 对象,为什么它会起作用? - 2

    如果您尝试在Ruby中的nil对象上调用方法,则会出现NoMethodError异常并显示消息:"undefinedmethod‘...’fornil:NilClass"然而,有一个tryRails中的方法,如果它被发送到一个nil对象,它只返回nil:require'rubygems'require'active_support/all'nil.try(:nonexisting_method)#noNoMethodErrorexceptionanymore那么try如何在内部工作以防止该异常? 最佳答案 像Ruby中的所有其他对象

  9. ruby - 为什么 SecureRandom.uuid 创建一个唯一的字符串? - 2

    关闭。这个问题需要detailsorclarity.它目前不接受答案。想改进这个问题吗?通过editingthispost添加细节并澄清问题.关闭8年前。Improvethisquestion为什么SecureRandom.uuid创建一个唯一的字符串?SecureRandom.uuid#=>"35cb4e30-54e1-49f9-b5ce-4134799eb2c0"SecureRandom.uuid方法创建的字符串从不重复?

  10. ruby-on-rails - 在 ruby​​ 中使用 gsub 函数替换单词 - 2

    我正在尝试用ruby​​中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了

随机推荐