2012-04-18 40 views
1

我傳遞這兩個簽名,一類爲模板類的模板參數的成員函數的實際指針。有沒有一種方法可以爲操作符重載有這樣的類的專業化?我試圖尋找在type_traitsstd::is_copy_assignable有提示,但似乎G ++採用內置插件(__has_trivial_copy爲例)。我可以在編譯時檢查會員功能是否爲操作員?

+0

你想知道(一)某一個指針到成員函數重載運算符或(b)該如。模板參數A實際上實現了A * A? – jpalecek 2012-04-18 12:08:13

+1

http://www.boost.org/doc/libs/1_49_0/libs/type_traits/doc/html/boost_typetraits/category/value_traits/operators.html – Anonymous 2012-04-18 12:09:10

+0

(a)。我想盡管實現將不得不檢查指向成員函數所屬的類型實現了被檢查的操作符。 – 2012-04-18 12:09:36

回答

0

嗯,我曾在這個問題上。

我認爲這是可能得到的結果,但它是相當複雜的,因爲要知道,如果它自己的模板參數之一是B類的運營商A級,必須先檢查B ::操作符存在,然後檢查它是否等於模板參數。這很快增加了任務的難度。

而且,我發現在測試時,使g ++有仍然是提前模板使用很差的支持。例如,該代碼就步驟2,即假設某一成員函數存在,檢查是否模板參數等於同一成員函數:

#include <iostream> 
using namespace std; 

struct Hello{ 
    int helloworld(){ 
     return 0; 
    } 
    int goodbyeworld(){ 
     return 0; 
    } 
}; 

template<typename T1, T1, typename T2, T2> struct is_same_method{ 
    static constexpr bool value=false; 
}; 

template<typename Return, typename Class, typename... Args, Return(Class::*member)(Args...)> 
struct is_same_method<Return(Class::*)(Args...), member, Return(Class::*)(Args...), member>{ 
    static constexpr bool value=true; 
}; 

#define method_test(a, b) is_same_method<decltype(a), a, decltype(b), b>::value 


template<typename T, T> struct what_am_I_passed; 

template<typename Return, typename Class, typename... Args, Return(Class::*member)(Args...)> 
struct what_am_I_passed<Return(Class::*)(Args...), member>{ 
    static void so_what(){ 
     /* 
     * error: ‘decltype (& Class:: helloworld)’ is not a valid type for a template constant parameter. 
     */ 
     cout<<"you passed me "<<(method_test(member, &Class::helloworld)?"helloworld":"something else")<<endl; 
    } 
}; 

int main(){ 
    what_am_I_passed<decltype(&Hello::helloworld), &Hello::helloworld>::so_what(); 
} 

現在,這個代碼失敗克++ 4.4,4.5崩潰4.6.1,並從4.6.2開始工作。

所有這些麻煩後,我決定把一些端口的邏輯在運行時。這是我結束了。

#include <iostream> 
#include <type_traits> 
using namespace std; 

template<typename mem_type, mem_type mem> struct operator_type{ 
    enum types{ 
     //complete me... 
     NONE=0, ADD, SUB, MUL, DIV, MOD, POW, UNM, EQ, NEQ, LT, LE, GT, GE, SUBSCRIPT, CALL 
    }; 
    static types what(){ return NONE; } 
}; 

typedef operator_type<int, 0>::types op_types; 

template<typename Return, typename Class, typename... Args, Return(Class::*mem)(Args...)> 
class operator_type<Return(Class::*)(Args...), mem>{ 

#define isOp(name, symbol, args)\ 
     template<typename Class_,int=0> static bool is##name(float&&){ return false; }\ 
     template<typename Class_, Return(Class_::*innermem)(Args...)=&Class_::operator symbol>\ 
     static bool is##name(int&&){ return innermem==mem && (args<0 || sizeof...(Args)==args); } 
#define testOp(name) if(is##name<Class>(0)) return op_types::name 

    //complete me... 
    isOp(ADD, +, 1) 
    isOp(SUB, -, 1) 
    isOp(MUL, *, 1) 
    isOp(DIV, /, 1) 
    isOp(MOD, %, 1) 
    isOp(POW, ^, 1) 
    isOp(UNM, -, 0) 
    isOp(EQ, ==, 1) 
    isOp(NEQ, !=, 1) 
    isOp(LT, <, 1) 
    isOp(LE, <=, 1) 
    isOp(GT, >, 1) 
    isOp(GE, >=, 1) 
    isOp(SUBSCRIPT, [], 1) 
    isOp(CALL,(), -1) 

public: 

    static op_types what(){ 
     //complete me... 
     testOp(ADD); 
     testOp(SUB); 
     testOp(MUL); 
     testOp(DIV); 
     testOp(MOD); 
     testOp(POW); 
     testOp(UNM); 
     testOp(EQ); 
     testOp(NEQ); 
     testOp(LT); 
     testOp(LE); 
     testOp(GT); 
     testOp(GE); 
     testOp(SUBSCRIPT); 
     testOp(CALL); 
     return op_types::NONE; 
    } 
}; 




template<typename T, T> struct wants_to_know_operators; 

template<typename Return, typename Class, typename... Args, Return(Class::*mem)(Args...)> 
struct wants_to_know_operators<Return(Class::*)(Args...), mem>{ 
    typedef operator_type<decltype(mem), mem> my_operator_type; 
    static void stuff(){ 
     switch(my_operator_type::what()){ 
     case op_types::NONE:  cout<<"this is not an operator"<<endl; break; 
     case op_types::CALL:  cout<<"this is operator()"<<endl; break; 
     case op_types::SUBSCRIPT: cout<<"this is operator[]"<<endl; break; 
     case op_types::SUB:   cout<<"this is operator-"<<endl; break; 
     case op_types::UNM:   cout<<"this is operator- (unary)"<<endl; break; 
     //complete me... 
     default: cout<<"something else..."<<endl; break; 
     } 
    } 
}; 

struct Test{ 
    void operator()(){ 

    } 
    Test& operator-(){ 
     return *this; 
    } 
    Test& operator-(int){ 
     return *this; 
    } 
    int operator[](int){ 
     return 0; 
    } 
    int operator[](iostream){ 
     return 0; 
    } 
    int operator==(int){ 
     return 0; 
    } 
    void f(){} 
}; 


int main(){ 
    wants_to_know_operators<decltype(&Test::f), &Test::f>::stuff(); 
    wants_to_know_operators<int(Test::*)(int), &Test::operator[]>::stuff(); 
    wants_to_know_operators<int(Test::*)(iostream), &Test::operator[]>::stuff(); 
    wants_to_know_operators<decltype(&Test::operator()), &Test::operator()>::stuff(); 
    wants_to_know_operators<decltype(&Test::operator==), &Test::operator==>::stuff(); 
    wants_to_know_operators<Test&(Test::*)(), &Test::operator- >::stuff(); 
    wants_to_know_operators<Test&(Test::*)(int), &Test::operator- >::stuff(); 
} 

語法有點麻煩,但它是我可以用模板解決的最好的。請注意,它可以區分同一運營商的不同過載。對於我的目標來說,這是足夠的,甚至是可取的,因爲整個過程就是將C++函數導出到Lua中,當然,在編譯時你不能將東西放到Lua堆棧上。

+0

所以你的代碼在當前版本的編譯器中工作,但你說它「仍然有非常差的支持」......嗯,你有那裏有趣的標準。也許你的意思是舊版本的gcc早於C++ 11 _對該未完成標準的支持很差? :) P.S.如果您發現當前版本中仍然存在錯誤,我希望您報告它們,如果沒有人報告它們,它們將不會得到修復。 – 2012-05-17 18:57:51

+0

@JonathanWakely也許我聽起來太激烈了。我的意思是,即使有一個像我一樣的小型項目,我在最近版本的g ++中遇到了錯誤(不是缺少實現,錯誤)。此外,支持似乎有點「不穩定」,因爲我也遇到了g ++ 4.6或4.7中的一些迴歸。這完全可以理解,因爲C++ 11非常新,功能集非常先進。當然,我報告了大部分我發現的東西。見http://gcc.gnu.org/bugzilla/show_bug.cgi?id=52744 http://gcc.gnu.org/bugzilla/show_bug.cgi?id=53009 http://gcc.gnu.org/bugzilla /show_bug.cgi?id=53181 – 2012-05-17 19:54:27

相關問題