Я передаю как подпись, так и фактический указатель функции-члена класса как параметры шаблона класса шаблона. Есть ли способ различной специализации такого класса для перегрузок операторов? Я попытался посмотреть в type_traits
и получить подсказку от std::is_copy_assignable
, но похоже, что g ++ использует встроенные модули (например, __has_trivial_copy
).Можно ли проверить время компиляции, если функция-член является оператором?
ответ
Ну, я работал над этим вопросом.
Я думаю, что можно получить результат, но это довольно сложно, потому что класс А, который хочет знать, является ли один из его собственных аргументов шаблона оператором класса B, должен сначала проверить, что оператор 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 _had_ плохой поддержке этого незавершенного стандарта? :) P.S. если вы обнаружили ошибки, которые все еще присутствуют в текущих версиях, надеюсь, вы сообщили о них, они не будут исправлены, если никто не сообщит об этом. –
@ JonathanВозвратитесь, может быть, я назвал слишком резким. Я имел в виду, что даже с небольшим хобби-проектом, как с моим, я столкнулся с ошибками (не пропускающими реализации, ошибки) в последних версиях 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 –
- 1. Как проверить, если класс является абстрактным, во время компиляции?
- 2. Является ли утверждение, принятое во время компиляции?
- 3. Можно ли проверить значения при компиляции?
- 4. Как проверить время компиляции?
- 5. Является ли «:::» оператором?
- 6. Можно ли проверить vbscript, если папка является символической ссылкой?
- 7. Можно ли индексировать массивы во время компиляции?
- 8. Быстрое время компиляции с нисходящим оператором коалесценции
- 9. Является ли время компиляции "strlen()" эффективным?
- 10. Является ли nameof() оцененным во время компиляции?
- 11. Rails: можно проверить, является ли строка двоичной?
- 12. Как проверить во время компиляции, если функция вызвана
- 13. Есть ли способ проверить во время компиляции, что константа является константой времени компиляции?
- 14. Можно проверить, является ли номер IN GROUP_CONCAT
- 15. Как проверить во время компиляции, что выражение является незаконным?
- 16. Проверьте, является ли пользователь оператором Bot :: BasicBot
- 17. Время компиляции проверяет, является ли базовый класс «интерфейсом»
- 18. Можно ли во время компиляции проверить, получен ли тип от некоторого экземпляра шаблона?
- 19. Делает ли время компиляции?
- 20. Можно ли бесконечно контактировать с оператором switch?
- 21. Проверьте, является ли число простым во время компиляции в C++
- 22. Android: проверить файл xml во время компиляции?
- 23. Можно ли проверить, если сделать нажата кнопка
- 24. Как проверить, имеет ли класс унаследованную функцию во время компиляции?
- 25. Можно ли оптимизировать время компиляции с оптимизацией времени соединения?
- 26. Проверка во время компиляции, если тип является указателем
- 27. Есть ли способ проверить, объявлена ли переменная во время компиляции?
- 28. Можно ли проверить, является ли значение int в C#?
- 29. Как проверить аннотацию во время компиляции?
- 30. если оптимизация во время компиляции
Вы хотите знать (a), что определенная функция-указатель-член является перегруженным оператором или (b), например. шаблонный аргумент A фактически реализует A * A? – jpalecek
http://www.boost.org/doc/libs/1_49_0/libs/type_traits/doc/html/boost_typetraits/category/value_traits/operators.html – Anonymous
(a). Я предполагаю, однако, что реализация должна будет проверить, что тип, к которому принадлежит указатель-член-функция, выполняет проверяемый оператор. –