2017-01-20 61 views
0

我一直在爲opencascade C++封裝到C#。 我的C++有點生疏,因爲我最近幾年主要使用C#。複雜的C++模板代碼

現在我遇到了以下問題,一直無法弄清楚如何糾正它:

#include <type_traits> 

//! Trait yielding true if class T1 is base of T2 but not the same 
template <class T1, class T2, class Dummy = void> 
struct is_base_but_not_same : std::is_base_of <T1, T2> {}; 

//! Explicit specialization of is_base_of trait to workaround the 
//! requirement of type to be complete when T1 and T2 are the same. 
template <class T1, class T2> 
struct is_base_but_not_same <T1, T2, typename std::enable_if <std::is_same <T1, T2>::value>::type> : std::false_type {}; 

template <class T> 
class handle 
{ 
public: 
    //! Down casting operator from handle to base type 
    template <class T2> 
    static typename std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type 
     DownCast(const handle<T2>& theObject) 
    { 
     return handle(dynamic_cast<T*>(const_cast<T2*>(theObject.get()))); 
    } 

    //! Down casting operator from pointer to base type 
    template <class T2> 
    static typename std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type 
     DownCast(const T2* thePtr) 
    { 
     return handle(dynamic_cast<T*>(const_cast<T2*>(thePtr))); 
    } 
}; 

class Foo 
{ 

}; 

typedef handle<Foo> Handle_Foo; 

Handle_Foo DownCastFoo(Handle_Foo const &T) { 
    return Handle_Foo::DownCast(T); 
} 

的compilor錯誤有以下幾種:

Error C2672 'handle<Foo>::DownCast': no matching overloaded function found 
Severity Code Description Project File Line Suppression State 
Error C2784 'std::enable_if<is_base_but_not_same<T2,T,void>::value,handle<T>>::type handle<T>::DownCast(const T2 *)': could not deduce template argument for 'const T2 *' from 'const Handle_Foo' 
Severity Code Description Project File Line Suppression State 
Error C2893 Failed to specialize function template 'std::enable_if<is_base_but_not_same<T2,T,void>::value,handle<T>>::type handle<T>::DownCast(const handle<T2> &)' 

任何人都可以點我在正確的方向?

+0

您好,我認爲這些代碼定義現在已完成,讓我知道如果我錯過了水手。 –

+1

您發佈的代碼至少包含一個錯字(我希望如此)。創建你的[mcve]。然後編譯它。獲取你想要修正的錯誤。如果你得到一個不同的錯誤,修復你的mcve。不要用手抄錄。複製代碼(通過複製粘貼),格式與空格,複製錯誤(通過複製粘貼),格式化爲空格。不要總結錯誤,包括所有警告和錯誤行。要求某人弄清楚什麼是錯字,什麼是你真正的錯誤是不可接受的,不好,不好,一般也不好。如果你的例子太長,那麼使它更小。 – Yakk

+0

第三次是他們說的魅力;) –

回答

0

在提供的示例中有多個錯誤。

首先,例如意味着對於handleT*構造和get()方法。這些添加到handle類:

explicit handle(T*); 
const T* get() const; 

其次,你正試圖從handle<Foo>下來投給handle<Foo>這是一場毫無意義的操作。 Foo甚至不是多態的。你的下調方法似乎專門設計爲不提供這種超載,因此你得到的錯誤。將Foo定義爲多態,並添加派生類Bar

struct Foo { virtual ~Foo() = default; }; 
struct Bar : public Foo {}; 

最後,改變DownCastFoo嘗試向下轉換Bar而不是Foo,並且該錯誤被解決。

typedef handle<Foo> Handle_Foo; 
typedef handle<Bar> Handle_Bar; 

Handle_Bar DownCastFoo(Handle_Foo const &T) { 
    return Handle_Bar::DownCast(T); 
} 

最後一點,那些const_cast氣色好可疑。不幸的是,您的示例沒有足夠的信息來提供更好的建議。


完全正確的示例

#include <type_traits> 

//! Trait yielding true if class T1 is base of T2 but not the same 
template <class T1, class T2, class Dummy = void> 
struct is_base_but_not_same : std::is_base_of <T1, T2> {}; 

//! Explicit specialization of is_base_of trait to workaround the 
//! requirement of type to be complete when T1 and T2 are the same. 
template <class T1, class T2> 
struct is_base_but_not_same <T1, T2, typename std::enable_if <std::is_same <T1, T2>::value>::type> : std::false_type {}; 

template <class T> 
class handle 
{ 
public: 
    explicit handle(T*); 
    const T* get() const; 
public: 
    //! Down casting operator from handle to base type 
    template <class T2> 
    static typename std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type 
     DownCast(const handle<T2>& theObject) 
    { 
     return handle(dynamic_cast<T*>(const_cast<T2*>(theObject.get()))); 
    } 

    //! Down casting operator from pointer to base type 
    template <class T2> 
    static typename std::enable_if<is_base_but_not_same<T2, T>::value, handle>::type 
     DownCast(const T2* thePtr) 
    { 
     return handle(dynamic_cast<T*>(const_cast<T2*>(thePtr))); 
    } 
}; 

struct Foo { virtual ~Foo() = default; }; 
struct Bar : public Foo {}; 

typedef handle<Foo> Handle_Foo; 
typedef handle<Bar> Handle_Bar; 

Handle_Bar DownCastFoo(Handle_Foo const &T) { 
    return Handle_Bar::DownCast(T); 
} 

編輯:它看起來像enable_if僅用於防止非法超載。如果您使用static_assert,您將得到更好的編譯錯誤。

示例使用static_assert

template <class T> 
class handle 
{ 
public: 
    explicit handle(T*); 
    const T* get() const; 
public: 
    //! Down casting operator from handle to base type 
    template <class T2> 
    static handle DownCast(const handle<T2>& theObject) 
    { 
     static_assert(std::is_same<T, T2>::value == false, 
      "Can't downcast from between identical types"); 
     static_assert(std::is_base_of<T2, T>::value, 
      "Can only down cast from a derived type to a base type"); 
     return handle(dynamic_cast<T*>(const_cast<T2*>(theObject.get()))); 
    } 

    //! Down casting operator from pointer to base type 
    template <class T2> 
    static handle DownCast(const T2* thePtr) 
    { 
     static_assert(std::is_same<T, T2>::value == false, 
      "Can't downcast from between identical types"); 
     static_assert(std::is_base_of<T2, T>::value, 
      "Can only down cast from a derived type to a base type"); 
     return handle(dynamic_cast<T*>(const_cast<T2*>(thePtr))); 
    } 
}; 

現在,您原來使用的情況下會產生錯誤信息"Can't downcast from between identical types"

struct Foo { virtual ~Foo() = default; }; 
struct Bar : public Foo {}; 

typedef handle<Foo> Handle_Foo; 

Handle_Foo DownCastFoo(Handle_Foo const &T) { 
    return Handle_Foo::DownCast(T); 
} 
+0

謝謝,這樣做更有意義。你知道6年前嘗試和別人製作的代碼編碼並不總是那麼容易。在一種語言中我甚至沒有編碼。在發佈問題時,我會盡量做到更精確。真的很感謝你的回答!我給你一個upvote(看起來沒有公開記錄,因爲新成員需要至少15個upvotes纔可以提供)。 –