У меня был некоторый класс как это:
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?
редактировать: На самом деле, потрудившись проверить мою теорию, оказалось, что я был неправ, в этом контексте 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;
Я думаю, причина в том, что в классе 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');
}