Is & decltype (object) :: memfn - misuse?

I had a class like:

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 to repeat the call bar1 / bar2, etc., and then check the return value again and again, so I wrote a macro and a variational pattern to handle these 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 (very strange error message)

main.cpp (37): error: type name not resolved
help_macro (t, bar, i, 'a');
^
main.cpp (37): error: expected a ")"
help_macro (t, bar, i, 'a');
^

I turned on C ++ 11 for ICC and confirmed that ICC13 supports the variational pattern and decltype Am I using it incorrectly or is it an ICC problem?

+4
source share
2 answers

Edit : actually bothered to check my theory, it turned out that I was wrong, in this context decltype(t) is Test , which can be shown static_assert(std::is_same<decltype(t), Test>::value, "not a reference")

So ICC (or the external EDG interface that it uses) probably just doesn't support decltype support in nested qualifiers, which was changed by DR 743

Using std::decay makes ICC acceptable, and therefore a useful solution.

Original, wrong, answer :

I think the ICC here, decltype(object) is actually Test& , and the reference type cannot have members, therefore &decltype(t)::memfn poorly formed.

The code can be simplified to:

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

Which g ++ and Clang accept, but ICC rejects, correctly IMHO.

You can fix this using std::remove_reference or std::decay

 #include <type_traits> // ... Test t; auto p = &std::decay<decltype(t)>::type::foo; 
+2
source

I think the reason is that there is no "bar" function in the Test class, but I'm not sure, since I do not have access to this compiler. However, the error message you sent indicates that there is an attempt to use the bar.

The following works for both gcc and 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
source

All Articles