Является ли & ampltype (объект) :: memfn неправильным использованием?

У меня был некоторый класс как это:

class Test {
public:
bool bar(int &i, char c) // some arguments are passed by ref, some are by value
{/*...*/}
bool foo(/*...*/)
{}
};

И я не хочу повторно вызывать bar1 / bar2 и т. Д., А затем проверять возвращаемое значение снова и снова, поэтому я написал макрос и шаблон с переменным числом аргументов для обработки этих вещей.

#define help_macro(object, memfn, ...) help_func(#object "." #memfn, \
object, &decltype(object)::memfn, ##__VA_ARGS__)

template<class T, typename Func, typename... Args>
void help_func(char const * name, T &&object, Func memfn, Args&&... args)
{
auto ret = (object.*memfn)(forward<Args>(args)...);
cout<<name<<":\t"<<(ret ? "OK" : "Oops")  // maybe I'll throw an exception here
<<endl;
}

И используйте это так

int i = 0;
Test t;
help_macro(t, bar, i, 'a');

Он работает на g ++ — 4.7 / Debian, но ICC13.0 / Win отказывается его компилировать (очень странное сообщение об ошибке)

main.cpp (37): ошибка: имя типа не допускается
help_macro (t, bar, i, ‘a’);
^
main.cpp (37): ошибка: ожидается «)»
help_macro (t, bar, i, ‘a’);
^

Я включил C ++ 11 для ICC и подтвердил, что ICC13 поддерживает шаблон variadic и decltype
Я использую это неправильно, или это проблема ICC?

4

Решение

редактировать: На самом деле, потрудившись проверить мою теорию, оказалось, что я был неправ, в этом контексте decltype(t) является Test как может быть показано static_assert(std::is_same<decltype(t), Test>::value, "not a reference")

Таким образом, ICC (или интерфейс EDG, который он использует), вероятно, просто не поддерживает decltype в спецификаторах вложенных имен, которые были изменены DR 743

С помощью std::decay делает Сделайте так, чтобы ICC принял это, и это полезный обходной путь.

Оригинал, неверный ответ:

Я думаю, что МУС прямо здесь, decltype(object) на самом деле Test& и ссылочный тип не может иметь членов, поэтому &decltype(t)::memfn плохо сформирован.

Код может быть упрощен до:

struct Test {
void foo() {}
};

int main()
{
Test t;
auto p = &decltype(t)::foo;
}

Которые G ++ и Clang принимают, но ICC отклоняет, правильно ИМХО.

Вы можете исправить это с помощью std::remove_reference или же std::decay

#include <type_traits>

// ...

Test t;
auto p = &std::decay<decltype(t)>::type::foo;
2

Другие решения

Я думаю, причина в том, что в классе Test нет функции ‘bar’, но я не уверен, что у меня нет доступа к этому компилятору. Однако сообщение об ошибке, которое вы разместили, показывает, что есть попытка использовать ‘bar’.

Следующие работы как на gcc, так и на clang

class Test {
public:
bool bar1(int &i, char c) // some arguments are passed by ref, some are by value
{return true;}
bool bar2(int &i, char c)
{return true;}
};

#define help_macro(object, memfn, ...) help_func(#object "." #memfn, \
object, &decltype(object)::memfn, ##__VA_ARGS__)

template<class T, typename Func, typename... Args>
void help_func(char const * name, T &&object, Func memfn, Args&&... args)
{
auto ret = (object.*memfn)(std::forward<Args>(args)...);
std::cout<<name<<":\t"<<(ret ? "OK" : "Oops")  // maybe I'll throw an exception here
<<std::endl;
}

int main()
{
int i = 0;
Test t;
//help_macro(t, bar, i, 'a');
help_macro(t, bar2, i, 'a');
}
0

По вопросам рекламы ammmcru@yandex.ru
Adblock
detector