2014-10-07 79 views
6

我有一種直覺VS2012在這一個上是錯誤的,但我不確定。程序在Visual Studio 2012中運行,但不是ideone.com

看過this question之後,我覺得想要實現類似的東西。

我的版本在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>>候選功能:

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是正確的,是否有任何簡單的解決這個代碼?

+3

與(*可能重複?*)相關:[非常量引用綁定到臨時的Visual Studio錯誤?](http://stackoverflow.com/q/16380966/1708801)...基本上gcc在這裏是正確的。如果在Visual Studio中使用'/ Za'構建,它也會失敗,[請參閱此鏈接](http://rextester.com/GYMOJ23021)。 – 2014-10-07 20:36:17

+3

這是愚蠢的投票結束這個問題,因爲*爲什麼不是這個代碼工作*。測試可能會更小,但它是一個完整的測試用例,編譯器之間的結果相互矛盾,並且對於大多數人來說這肯定不明顯。 – 2014-10-07 20:43:37

回答

2

Ideone(實際上,GCC)在這裏是正確的。在Visual Studio中,它是由於臭名昭着的擴展而編譯的,它允許臨時綁定到非常量左值引用(標準禁止)。

我看到幾個可能的方式在標準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 >>過載服用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! 
} 

當然,理想情況下,您也可以提供混合的&, &&&&, &重載。

2

第一個模板基本上失敗了,因爲您無法將臨時值 - IntSquare() - 綁定到非常量左值引用。

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

+0

+1我發現兩個答案都有幫助,但是我和其他人一起去了。 – jliv902 2014-10-07 21:07:14

相關問題