[英]Program runs in Visual Studio 2012 but not ideone.com
我有一种直觉VS2012这个错了,但我不确定。
看完这个问题之后 ,我觉得要尝试实现类似的东西。
我的版本在Visual Studio 2012上运行良好,但甚至不在Ideone上编译。
这是我的主界面:
#include <iostream>
#include <string>
template <class In, class Out>
struct Pipe
{
typedef In in_type ;
typedef Out out_type ;
In in_val ;
Pipe (const in_type &in_val = in_type()) : in_val (in_val)
{
}
virtual auto operator () () const -> out_type
{
return out_type () ;
}
};
template <class In, class Out, class Out2>
auto operator>> (const Pipe <In, Out> &lhs, Pipe <Out, Out2> &rhs) -> Pipe <Out, Out2>&
{
rhs = lhs () ;
return rhs ;
}
template <class In, class Out>
auto operator>> (const Pipe <In, Out> &lhs, Out &rhs) -> Out&
{
rhs = lhs () ;
return rhs ;
}
以下是一些测试类:
struct StringToInt : public Pipe <std::string, int>
{
StringToInt (const std::string &s = "") : Pipe <in_type, out_type> (s)
{
}
auto operator () () const -> out_type
{
return std::stoi (in_val) ;
}
};
struct IntSquare : public Pipe <int, int>
{
IntSquare (int n = 0) : Pipe <in_type, out_type> (n)
{
}
auto operator () () const -> out_type
{
return in_val * in_val ;
}
};
struct DivideBy42F : public Pipe <int, float>
{
DivideBy42F (int n = 0) : Pipe <in_type, out_type> (n)
{
}
auto operator () () const -> out_type
{
return static_cast <float> (in_val) / 42.0f ;
}
};
这是驱动程序:
int main ()
{
float out = 0 ;
StringToInt ("42") >> IntSquare () >> DivideBy42F () >> out ;
std::cout << out << "\n" ;
return 0 ;
}
Ideone抱怨模板扣除,无法找到正确的operator>>
candidate函数:
prog.cpp: In function ‘int main()’:
prog.cpp:75:21: error: no match for ‘operator>>’ (operand types are ‘StringToInt’ and ‘IntSquare’)
StringToInt ("42") >> IntSquare () >> DivideBy42F () >> out ;
^
prog.cpp:75:21: note: candidates are:
prog.cpp:23:6: note: Pipe<Out, Out2>& operator>>(const Pipe<In, Out>&, Pipe<Out, Out2>&) [with In = std::basic_string<char>; Out = int; Out2 = int]
auto operator>> (const Pipe <In, Out> &lhs, Pipe <Out, Out2> &rhs) -> Pipe <Out, Out2>&
^
prog.cpp:23:6: note: no known conversion for argument 2 from ‘IntSquare’ to ‘Pipe<int, int>&’
prog.cpp:30:6: note: template<class In, class Out> Out& operator>>(const Pipe<In, Out>&, Out&)
auto operator>> (const Pipe <In, Out> &lhs, Out &rhs) -> Out&
^
prog.cpp:30:6: note: template argument deduction/substitution failed:
prog.cpp:75:35: note: deduced conflicting types for parameter ‘Out’ (‘int’ and ‘IntSquare’)
StringToInt ("42") >> IntSquare () >> DivideBy42F () >> out ;
哪个编译器正确? 如果Ideone是正确的,这个代码是否有任何简单的解决方法?
第一个模板基本上失败了,因为你不能将prvalue临时 - IntSquare ()
- 绑定到非const左值引用。
no known conversion for argument 2 from ‘IntSquare’ to ‘Pipe<int, int>&’
这表示您无法使用IntSquare
类型的prvalue初始化Pipe<int, int>&
。 遗憾的是,错误消息中未明确提及值类别。 虽然这是一个标准规则,VC ++忽略了它来缓解(或麻烦)C ++ - 程序员的日常生活。
第二个模板
template <class In, class Out>
auto operator>> (const Pipe <In, Out> &lhs, Out &rhs) -> Out&
{
rhs = lhs () ;
return rhs ;
}
失败是因为两个不同的推论Out
两个不同的类型 - 第一个是int
(对于lhs
),第二个是IntSquare
。
Ideone(实际上,GCC)在这里是正确的。 在Visual Studio中,它编译是因为臭名昭着的扩展允许临时绑定到非const左值引用(标准禁止)。
我在标准C ++中看到了几种可能的解决方法:
一,不要使用临时管道阶段:
int main ()
{
float out = 0 ;
StringToInt stage1("42");
IntSquare stage2;
DivideBy24F stage3;
stage1 >> stage2 >> stage3 >> out ;
std::cout << out << "\n" ;
return 0 ;
}
二,创建一个“停留”功能(与std::move
相反),并使用:
template <class T>
T& stay(T &&x) { return x; }
int main ()
{
float out = 0 ;
stay(StringToInt ("42")) >> stay(IntSquare ()) >> stay(DivideBy42F ()) >> out ;
std::cout << out << "\n" ;
return 0 ;
}
三,提供operator >>
的过载operator >>
取r值参考:
template <class In, class Out, class Out2>
auto operator>> (const Pipe <In, Out> &&lhs, Pipe <Out, Out2> &&rhs) -> Pipe <Out, Out2>&
{
return lhs >> rhs; // Notice that lhs and rhs are lvalues!
}
当然,理想情况下你也提供混合&, &&
和&&, &
重载。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.