I had some class like this:
class Test {
public:
bool bar(int &i, char c) // some arguments are passed by ref, some are by value
{/*...*/}
bool foo(/*...*/)
{}
};
And I don’t want repeatly call bar1/bar2, etc. and then check the return value again and again, so I wrote a macro and variadic template to handle those things
#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;
}
And use it like this
int i = 0;
Test t;
help_macro(t, bar, i, 'a');
It works on g++-4.7/Debian, but ICC13.0/Win refuses to compile it(a very strange error message)
main.cpp(37): error : type name is not allowed
help_macro(t, bar, i, ‘a’);
^
main.cpp(37): error : expected a “)”
help_macro(t, bar, i, ‘a’);
^
I turn on the C++11 for ICC, and confirmed that ICC13 support variadic template and decltype
Do I use it incorrectly or it’s ICC’s problem?
Edit: Having actually bothered to test my theory it turns out I was wrong, in that context
decltype(t)isTestas can be shown by astatic_assert(std::is_same<decltype(t), Test>::value, "not a reference")So ICC (or the EDG front end it uses) probably just doesn’t properly support using
decltypein nested-name-specifiers, which was changed by DR 743Using
std::decaydoes make ICC accept it though, and so is a useful workaround.Original, wrong, answer:
I think ICC is right here,
decltype(object)is actuallyTest&and a reference type cannot have members, so&decltype(t)::memfnis ill-formed.The code can be simplified to:
Which G++ and Clang accept, but ICC rejects, correctly IMHO.
You can fix it by using
std::remove_referenceorstd::decay