我傳遞這兩個簽名,一類爲模板類的模板參數的成員函數的實際指針。有沒有一種方法可以爲操作符重載有這樣的類的專業化?我試圖尋找在type_traits
和std::is_copy_assignable
有提示,但似乎G ++採用內置插件(__has_trivial_copy
爲例)。我可以在編譯時檢查會員功能是否爲操作員?
回答
嗯,我曾在這個問題上。
我認爲這是可能得到的結果,但它是相當複雜的,因爲要知道,如果它自己的模板參數之一是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堆棧上。
所以你的代碼在當前版本的編譯器中工作,但你說它「仍然有非常差的支持」......嗯,你有那裏有趣的標準。也許你的意思是舊版本的gcc早於C++ 11 _對該未完成標準的支持很差? :) P.S.如果您發現當前版本中仍然存在錯誤,我希望您報告它們,如果沒有人報告它們,它們將不會得到修復。 – 2012-05-17 18:57:51
@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
- 1. 檢查會員是否爲
- 2. 檢查會員功能是否存在,是否繼承SFINAE
- 3. 在編譯時類是否有一個成員variabe或功能
- 4. 或操作員作爲功能開關
- 5. 是否可以使用?班級成員的操作員?
- 6. 是否可以在編譯時檢查const值是否已知?
- 7. 檢查用戶是否是會員
- 8. 我可以用MemberInfo檢查成員是否是委託人?
- 9. 如何爲操作員分配功能?
- 10. WSS 3.0功能 - 檢查用戶是否爲農場管理員
- 11. 爲什麼操作員在檢查類型時是否考慮了顯式操作符是否被覆蓋?
- 12. Python - 是否可以爲操作員設置變量?
- 13. 檢查編譯時iso_c_binding是否可用
- 14. 操作員新操作員和新操作員不能重載?
- 15. 會員模板功能。爲什麼不編譯?
- 16. 我可以檢查是否設置了聯盟成員?
- 17. 我可以在If語句中使用操作員2操作員
- 18. Coffeescript Object作爲私人會員,是否有可能?
- 19. 我可以在Typescript中編寫一個演員操作符嗎?
- 20. 是否可以在開關操作員中解構對象?
- 21. 是否可以在COQ中實施派生操作員?
- 22. 我可以檢查異步功能是否正在運行?
- 23. 檢查是否子成員爲NULL
- 24. 如何更改操作員' - '的智能操作員行爲?
- 25. 是否可以讓操作員在操作中使用先驗值
- 26. 如何在一個操作中查找並檢查用戶是否是成員?
- 27. QWidgets是否成爲會員?
- 28. Ember - 檢查會員是否可以查看某個組的信息
- 29. ISO C90/99檢查是否存在編譯器特定功能
- 30. 功能函數的編譯時檢查
你想知道(一)某一個指針到成員函數重載運算符或(b)該如。模板參數A實際上實現了A * A? – jpalecek 2012-04-18 12:08:13
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
(a)。我想盡管實現將不得不檢查指向成員函數所屬的類型實現了被檢查的操作符。 – 2012-04-18 12:09:36