我正在尝试为类的模板化转换运算符指定模板参数,但我似乎无法获得正确的语法。
#include <iostream>
using namespace std;
class C
{
int i_;
public:
C(int i) : i_(i) {}
template<int adder> int get() { return i_ + adder; }
template<int adder> int operator()() { return i_ + adder; }
template<int adder> operator int() { return i_ + adder; }
// If I add a default argument to operator int()'s adder template parameter this compiles fine
// (of course, I still can't figure out how to specify it...)
};
int main(int, char*[])
{
C c(10);
cout << c.get<2>() << endl; // I can specify template argument here the regular way.
// cout << c() << endl; // No template argument specified, so I wouldn't have expected this to work.
cout << c.operator()<3>() << endl; // We have to call it this way.
// cout << (int)c << endl; // In the same vein I wouldn't expect this to work either.
cout << c.operator int<4>() << endl; // But how do I specify template argument here? This seems to be an error for some compilers.
return 0;
}
相同的代码在 http://liveworkspace.org/code/35sqXe$4
使用 g++ 4.7.2 编译时
$ g++ -std=c++11 -Wall -W -pedantic "template conversion operator.cpp"
Compilation finished with errors:
source.cpp: In function 'int main(int, char**)':
source.cpp:23:23: error: 'int' is not a template
source.cpp:23:30: error: no matching function for call to 'C::operator int()'
source.cpp:23:30: note: candidate is:
source.cpp:11:24: note: template<int adder> C::operator int()
source.cpp:11:24: note: template argument deduction/substitution failed:
source.cpp:23:30: note: couldn't deduce template parameter 'adder'
使用 g++ 4.8.0 (20130224) 编译时
$ g++ -std=c++11 -Wall -W -pedantic "template conversion operator.cpp"
Compilation finished with errors:
source.cpp: In function 'int main(int, char**)':
source.cpp:23:23: error: 'int' is not a template
cout << c.operator int<4>() << endl;
^
source.cpp:23:30: error: no matching function for call to 'C::operator int()'
cout << c.operator int<4>() << endl;
^
source.cpp:23:30: note: candidate is:
source.cpp:11:24: note: template<int adder> C::operator int()
template<int adder> operator int() { return i_ + adder; }
^
source.cpp:11:24: note: template argument deduction/substitution failed:
source.cpp:23:30: note: couldn't deduce template parameter 'adder'
cout << c.operator int<4>() << endl;
^
使用 clang++ 3.2 编译时
$ clang++ -std=c++11 -Wall -W -pedantic "template conversion operator.cpp"
Compilation finished with errors:
source.cpp:23:12: error: reference to non-static member function must be called
cout << c.operator int<4>() << endl;
^~~~~~~~~~~~~~
source.cpp:23:30: error: expected expression
cout << c.operator int<4>() << endl;
^
2 errors generated.
使用 icc 13.0.1 编译时
$ icc -std=c++11 -Wall -W -pedantic "template conversion operator.cpp"
Compilation finished with warnings:
source.cpp(11): warning #488: constant "adder" is not used in declaring the parameter types of function template "C::operator int"
template<int adder> operator int() { return i_ + adder; }
^
除警告外,icc 似乎工作正常。
这些是编译器错误吗?还是我的语法有问题?
编辑
自从 Yakk 问我原来/实际的问题是什么:
我有一个 Ptr 类(以它指向的类型为模板),我想将 Ptr 转换为 const T。(虽然我知道在这种情况下这并不重要,)我希望转换运算符不如果 T 已经是 const 类型,就在那里。由于您没有为转换运算符指定返回类型或方法参数,因此我将 enable_if 作为方法模板参数的一部分。
正如 Yakk(和其他问题中的其他人)发布的那样,一个简单的 template <typename = typename std::enable_if<!std::is_const<T>::value>::type>不起作用,因为当实例化 Ptr 时,T 在编译器到达此声明时已知。由于没有推导 T,因此不存在 SFINAE。因为我们知道!is_const<T>::value为假,没有“类型”成员,声明无效。使模板依赖于新类型 (U),推导 U,然后检查 U 是否与 T 相同,以及 T 不是 const,然后进行无效声明是 SFINAE 的有效使用并且有效正如预期的那样。
template <typename T>
class Ptr
{
template <typename U,
typename = typename std::enable_if<std::is_same<T, U>::value &&
!std::is_const<U>::value>::type>
operator Ptr<const U>() const { return active; }
};
但后来我对自己说,这是一个模板化的成员函数。这些模板参数不必保留为默认值,任何实例化该函数的人都可以指定它们。对于任何其他 operator xxx 函数,执行此操作的语法很明显并且有效(请参阅上面的 operator())。对于这个例子:
Ptr<const int> ci;
ci.operator Ptr<const int><const int, void>(); // assuming this syntax is valid
void(或那里的任何其他类型)将指定转换运算符的第二个模板参数,并且不会考虑包含 enable_if 的默认值。当我试图使它不存在时,这将使该方法存在。
但是 gcc、clang 和 msvc 似乎对这种语法有问题。我假设因为转换运算符拼写为 operator typename ,具有模板参数会使编译器感到困惑,认为它们是用于类型名而不是运算符。
确实有变通办法(只包括转换运算符,当 T 已经是 const 时转换为 const T 不会造成任何伤害),但那是针对这个特定问题的。也许无法为转换运算符指定模板参数,因此,让这些类型被推导/默认就可以了。或者也许它有一个语法(icc 似乎接受它......),所以我向用户开放自己指定模板参数和实例化我不想要它们的方法。我已经有了针对我的特定问题的解决方案(在类型确实重要的时候,在转换运算符的类型检查中使用 static_assert),但这个问题是关于 C++ 语言及其语法的。顶部的 C 类只是我能想到的搜索该语法的最简单方法。
最佳答案
有点不清楚您要实现的目标...通常没有充分的理由让所有这些成员函数成为模板,您也可以将它们设为采用 adder 的常规函数。作为论点。
get函数,好吧,并不是真正的获取,而是添加,所以你可以称它为add .函数调用运算符 operator()()很可能需要一个int作为论据。转换运算符为 int从字面上看,作为模板没有任何意义,并且不能按定义调用。如果你坚持要 get和 operator()作为模板,您可以将它们称为:
C c(0);
c.get<5>(); // 5
c<5>(); // 5
但我建议您重新考虑设计,确定您真正需要什么以及模板是否可行...(请注意,即使在非模板版本中,转换为int 采用值,您不是转换,而是创建一个不同的 int !)
关于c++如何为类的模板化转换运算符指定参数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15305891/
我的目标是转换表单输入,例如“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看起来疯狂不安全。所以,功能正常,
我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h
Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack
我需要读入一个包含数字列表的文件。此代码读取文件并将其放入二维数组中。现在我需要获取数组中所有数字的平均值,但我需要将数组的内容更改为int。有什么想法可以将to_i方法放在哪里吗?ClassTerraindefinitializefile_name@input=IO.readlines(file_name)#readinfile@size=@input[0].to_i@land=[@size]x=1whilex 最佳答案 只需将数组映射为整数:@land边注如果你想得到一条线的平均值,你可以这样做:values=@input[x]
这道题是thisquestion的逆题.给定一个散列,每个键都有一个数组,例如{[:a,:b,:c]=>1,[:a,:b,:d]=>2,[:a,:e]=>3,[:f]=>4,}将其转换为嵌套哈希的最佳方法是什么{:a=>{:b=>{:c=>1,:d=>2},:e=>3,},:f=>4,} 最佳答案 这是一个迭代的解决方案,递归的解决方案留给读者作为练习:defconvert(h={})ret={}h.eachdo|k,v|node=retk[0..-2].each{|x|node[x]||={};node=node[x]}node[
exe应该在我打开页面时运行。异步进程需要运行。有什么方法可以在ruby中使用两个参数异步运行exe吗?我已经尝试过ruby命令-system()、exec()但它正在等待过程完成。我需要用参数启动exe,无需等待进程完成是否有任何rubygems会支持我的问题? 最佳答案 您可以使用Process.spawn和Process.wait2:pid=Process.spawn'your.exe','--option'#Later...pid,status=Process.wait2pid您的程序将作为解释器的子进程执行。除
我刚刚为fedora安装了emacs。我想用emacs编写ruby。为ruby提供代码提示、代码完成类型功能所需的工具、扩展是什么? 最佳答案 ruby-mode已经包含在Emacs23之后的版本中。不过,它也可以通过ELPA获得。您可能感兴趣的其他一些事情是集成RVM、feature-mode(Cucumber)、rspec-mode、ruby-electric、inf-ruby、rinari(用于Rails)等。这是我当前用于Ruby开发的Emacs配置:https://github.com/citizen428/emacs
我的瘦服务器配置了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