我正在尝试重现视频 C++ Weekly - Ep 48 - C++17's Variadic using 的结果,但失败了。该问题可以简化为以下代码段。
假设我有这样的通用结构:
template <class... T>
struct Container {
template <class... U>
Container(U... us) {}
};
现在我可以初始化一个 Container带有任何参数,例如
auto d = Container(1,2,3);
但是,编译器永远不会知道 d 是什么类型是。为了解决这个问题,我们应该提供一个推导指南,例如
template <class... U>
Container(U...) -> Container<double, int, bool>
根据视频,编译器现在应该知道d类型为 Container<double, int, bool> .
但是,代码没有按预期工作。打印时typeid(d).name() ,输出将始终为 9ContainerIJEE , 翻译成 Container<> ,无论我如何更改推导指南中的返回类型,都表明这样的指南根本不指导编译器。
我正在使用 gcc-7-snapshot-20170402 ,视频中的编译器是gcc-7-snapshot-20170130 .
谁能告诉我这里出了什么问题?
顺便说一句,如果我明确地写
Container<bool, int> d = Container(1,2,3);
Container<char, char, char> d = Container(1,2,3);
...
代码将始终编译,并提供类似 9containerIJbiEE
的输出和 9containerIJcccEE .
最佳答案
Now I can initialize a Container with any arguments, like
auto d = Container(1,2,3);However, the compiler will never know what type the
dis.
这不是完全准确的。 d 的类型是Container<>这里。让我们从构造函数的模板推导转向简单的函数模板:
template <class... Ts, class... Us>
void foo(Us... );
foo(1, 2, 3);
该函数调用完全没问题 - 我们推断 Us成为{int,int,int}我们推断Ts成为{} .那是因为 [temp.arg.explicit]/3 :
A trailing template parameter pack not otherwise deduced will be deduced to an empty sequence of template arguments. If all of the template arguments can be deduced, they may all be omitted; in this case, the empty template argument list
<>itself may also be omitted.
现在,什么是trailing 模板参数包?这是未指定的。但是这里Ts...可以推导为空,所以它是。请注意,这有一些奇怪的含义,例如:
template <class... Ts> void g(std::tuple<Ts...> );
g({}); // ok, calls g<>?
回到最初的问题。声明
Container d(1, 2, 3);
没有任何推导指南是良构的,因为我们可以成功地进行模板推导并推导Ts...因为是空的。也就是说,它完全等同于:
Container<> d(1, 2, 3);
那么当我们添加推导指南时会发生什么?现在,我们正在有效地执行以下之间的重载决议:
template <class... Ts, class... Us>
Container<Ts...> f(Us... ); // the constructor template
template <class... Us>
Container<double, int, bool> f(Us... ); // the deduction guide
f(1, 2, 3); // what does this return?
确定最佳可行候选人的决胜局在 [over.match.best] 中,其中相关的两个是:
Given these definitions, a viable function
F1is defined to be a better function than another viable functionF2if [...]
F1andF2are function template specializations, and the function template forF1is more specialized than the template forF2according to the partial ordering rules described in [temp.func.order], or, if not that,F1is generated from a deduction-guide ([over.match.class.deduct]) andF2is not, or, if not that, [...]
函数模板偏序 is really quite complicated并且编译器并不完全同意在所有情况下该怎么做。但在这种情况下,我会说这是一个 gcc 错误(我提交了 80871 )。根据[temp.deduct.partial] :
The types used to determine the ordering depend on the context in which the partial ordering is done:
- In the context of a function call, the types used are those function parameter types for which the function call has arguments.
也就是Ts...在第一个函数模板(从构造函数合成的模板)中不用于偏序。这使得两个函数模板相同,因此没有一个比另一个更专业。我们应该然后进入下一个项目符号,它告诉我们更喜欢推导指南而不是构造函数并以 Container<double, int, bool> 结束。 .然而,gcc 出于某种原因认为第一个函数模板更专业,因此在进入推导指南决胜局之前选择它,这就是为什么它以 Container<> 结尾的原因。 .
关于c++ - 可变参数模板构造函数的推导指南失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43304188/
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我的瘦服务器配置了nginx,我的ROR应用程序正在它们上运行。在我发布代码更新时运行thinrestart会给我的应用程序带来一些停机时间。我试图弄清楚如何优雅地重启正在运行的Thin实例,但找不到好的解决方案。有没有人能做到这一点? 最佳答案 #Restartjustthethinserverdescribedbythatconfigsudothin-C/etc/thin/mysite.ymlrestartNginx将继续运行并代理请求。如果您将Nginx设置为使用多个上游服务器,例如server{listen80;server
我正在使用puppet为ruby程序提供一组常量。我需要提供一组主机名,我的程序将对其进行迭代。在我之前使用的bash脚本中,我只是将它作为一个puppet变量hosts=>"host1,host2"我将其提供给bash脚本作为HOSTS=显然这对ruby不太适用——我需要它的格式hosts=["host1","host2"]自从phosts和putsmy_array.inspect提供输出["host1","host2"]我希望使用其中之一。不幸的是,我终其一生都无法弄清楚如何让它发挥作用。我尝试了以下各项:我发现某处他们指出我需要在函数调用前放置“function_”……这
我有一些Ruby代码,如下所示:Something.createdo|x|x.foo=barend我想编写一个测试,它使用double代替block参数x,这样我就可以调用:x_double.should_receive(:foo).with("whatever").这可能吗? 最佳答案 specify'something'dox=doublex.should_receive(:foo=).with("whatever")Something.should_receive(:create).and_yield(x)#callthere
我正在为一个项目制作一个简单的shell,我希望像在Bash中一样解析参数字符串。foobar"helloworld"fooz应该变成:["foo","bar","helloworld","fooz"]等等。到目前为止,我一直在使用CSV::parse_line,将列分隔符设置为""和.compact输出。问题是我现在必须选择是要支持单引号还是双引号。CSV不支持超过一个分隔符。Python有一个名为shlex的模块:>>>shlex.split("Test'helloworld'foo")['Test','helloworld','foo']>>>shlex.split('Test"
我想在一个没有Sass引擎的类中使用Sass颜色函数。我已经在项目中使用了sassgem,所以我认为搭载会像以下一样简单:classRectangleincludeSass::Script::FunctionsdefcolorSass::Script::Color.new([0x82,0x39,0x06])enddefrender#hamlengineexecutedwithcontextofself#sothatwithintemlateicouldcall#%stop{offset:'0%',stop:{color:lighten(color)}}endend更新:参见上面的#re
我不确定传递给方法的对象的类型是否正确。我可能会将一个字符串传递给一个只能处理整数的函数。某种运行时保证怎么样?我看不到比以下更好的选择:defsomeFixNumMangler(input)raise"wrongtype:integerrequired"unlessinput.class==FixNumother_stuffend有更好的选择吗? 最佳答案 使用Kernel#Integer在使用之前转换输入的方法。当无法以任何合理的方式将输入转换为整数时,它将引发ArgumentError。defmy_method(number)
两者都可以defsetup(options={})options.reverse_merge:size=>25,:velocity=>10end和defsetup(options={}){:size=>25,:velocity=>10}.merge(options)end在方法的参数中分配默认值。问题是:哪个更好?您更愿意使用哪一个?在性能、代码可读性或其他方面有什么不同吗?编辑:我无意中添加了bang(!)...并不是要询问nobang方法与bang方法之间的区别 最佳答案 我倾向于使用reverse_merge方法:option
我正在尝试用ruby中的gsub函数替换字符串中的某些单词,但有时效果很好,在某些情况下会出现此错误?这种格式有什么问题吗NoMethodError(undefinedmethod`gsub!'fornil:NilClass):模型.rbclassTest"replacethisID1",WAY=>"replacethisID2andID3",DELTA=>"replacethisID4"}end另一个模型.rbclassCheck 最佳答案 啊,我找到了!gsub!是一个非常奇怪的方法。首先,它替换了字符串,所以它实际上修改了
我已经构建了一些serverspec代码来在多个主机上运行一组测试。问题是当任何测试失败时,测试会在当前主机停止。即使测试失败,我也希望它继续在所有主机上运行。Rakefile:namespace:specdotask:all=>hosts.map{|h|'spec:'+h.split('.')[0]}hosts.eachdo|host|begindesc"Runserverspecto#{host}"RSpec::Core::RakeTask.new(host)do|t|ENV['TARGET_HOST']=hostt.pattern="spec/cfengine3/*_spec.r