Need help with workaround for MSVC bug

On MSVC, the following correct code produces error C2896: 'void operator ||(T,void (__cdecl *)(tag<X>))' : cannot use function template 'void bar(tag<X>)' as a function argument. struct foo { }; template <int X> struct tag { }; template <int X> void bar( tag<X> ) { } template <class T,int X> void operator||(T, void(*)(tag<X>)) { } int main() { foo()||bar<1>; } My goal is to have an operator|| overload that deduces tag<X> implicitly, but without using parenthesis, that is, foo()||bar<1>() wouldn't be satisfactory. Doesn't seem possible, but still I decided to ask. Any ideas? Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Emil Dotchevski wrote:
On MSVC, the following correct code produces error C2896: 'void operator ||(T,void (__cdecl *)(tag<X>))' : cannot use function template 'void bar(tag<X>)' as a function argument.
struct foo { };
template <int X> struct tag { };
template <int X> void bar( tag<X> ) { }
template <class T,int X> void operator||(T, void(*)(tag<X>)) { }
int main() { foo()||bar<1>; }
I think the problem is that the function template is a __thiscall * rather than the default __cdecl *. Thus, for MSVC (only), adding the following might solve your problem: template <class T, int X> void operator ||(T, void (__thiscall *)(tag<X>)) { } _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

On Thu, Sep 17, 2009 at 1:46 PM, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Emil Dotchevski wrote:
On MSVC, the following correct code produces error C2896: 'void operator ||(T,void (__cdecl *)(tag<X>))' : cannot use function template 'void bar(tag<X>)' as a function argument.
struct foo { };
template <int X> struct tag { };
template <int X> void bar( tag<X> ) { }
template <class T,int X> void operator||(T, void(*)(tag<X>)) { }
int main() { foo()||bar<1>; }
I think the problem is that the function template is a __thiscall * rather than the default __cdecl *. Thus, for MSVC (only), adding the following might solve your problem:
template <class T, int X> void operator ||(T, void (__thiscall *)(tag<X>)) { }
No it isn't __thiscall, bar is a global function template (op|| is also global.) Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

Emil Dotchevski wrote:
On Thu, Sep 17, 2009 at 1:46 PM, Stewart, Robert <Robert.Stewart@sig.com> wrote:
Emil Dotchevski wrote:
I think the problem is that the function template is a __thiscall * rather than the default __cdecl *. Thus, for MSVC (only), adding the following might solve your problem:
template <class T, int X> void operator ||(T, void (__thiscall *)(tag<X>)) { }
No it isn't __thiscall, bar is a global function template (op|| is also global.)
I knew that. I was just thinking, "not __cdecl," and "__thiscall" jumped into my head. Sorry about that. There are also __stdcall and __fastcall. _____ Rob Stewart robert.stewart@sig.com Software Engineer, Core Software using std::disclaimer; Susquehanna International Group, LLP http://www.sig.com IMPORTANT: The information contained in this email and/or its attachments is confidential. If you are not the intended recipient, please notify the sender immediately by reply and immediately delete this message and all its attachments. Any review, use, reproduction, disclosure or dissemination of this message or any attachment by an unintended recipient is strictly prohibited. Neither this message nor any attachment is intended as or should be construed as an offer, solicitation or recommendation to buy or sell any security or other financial instrument. Neither the sender, his or her employer nor any of their respective affiliates makes any warranties as to the completeness or accuracy of any of the information contained herein or that this message or any of its attachments is free of viruses.

Emil Dotchevski wrote:
On MSVC, the following correct code produces error C2896: 'void operator ||(T,void (__cdecl *)(tag<X>))' : cannot use function template 'void bar(tag<X>)' as a function argument.
struct foo { };
template <int X> struct tag { };
template <int X> void bar( tag<X> ) { }
template <class T,int X> void operator||(T, void(*)(tag<X>)) { }
int main() { foo()||bar<1>; }
My goal is to have an operator|| overload that deduces tag<X> implicitly, but without using parenthesis, that is, foo()||bar<1>() wouldn't be satisfactory. Doesn't seem possible, but still I decided to ask. Any ideas?
Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode
What about statically initialized pod objects, like the placeholder arguments in phoenix or lambda? I guess that only works if you have a (reasonably) bounded set from which X can come from... - Jeff

On Thu, Sep 17, 2009 at 4:27 PM, Jeffrey Hellrung <jhellrung@ucla.edu> wrote:
Emil Dotchevski wrote:
On MSVC, the following correct code produces error C2896: 'void operator ||(T,void (__cdecl *)(tag<X>))' : cannot use function template 'void bar(tag<X>)' as a function argument.
struct foo { };
template <int X> struct tag { };
template <int X> void bar( tag<X> ) { }
template <class T,int X> void operator||(T, void(*)(tag<X>)) { }
int main() { foo()||bar<1>; }
My goal is to have an operator|| overload that deduces tag<X> implicitly, but without using parenthesis, that is, foo()||bar<1>() wouldn't be satisfactory. Doesn't seem possible, but still I decided to ask. Any ideas?
What about statically initialized pod objects, like the placeholder arguments in phoenix or lambda?
I guess that only works if you have a (reasonably) bounded set from which X can come from...
You mean something like _1, _2, etc? Yes that could work but it's not ideal. Also, I found some other curiosities, like the fact that this declaration for op|| works: template <class T> void operator||(T, void(*)(tag<1>)) { } Presumably, I could provide K overloads instead of using the X template argument. That's silly, but it has the same limitations of the _1, _2 approach and has the benefit of not being silly on other compilers. I've also found that my original code works fine if I overload the comma operator instead of ||. Go figure... Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

On Thu, Sep 17, 2009 at 4:47 PM, Steven Watanabe <watanabesj@gmail.com> wrote:
AMDG
Emil Dotchevski wrote:
I've also found that my original code works fine if I overload the comma operator instead of ||. Go figure...
It compiles, but it calls the built-in comma operator.
Oh right. Haha :) Emil Dotchevski Reverge Studios, Inc. http://www.revergestudios.com/reblog/index.php?n=ReCode

-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1 On Thursday 17 September 2009, Emil Dotchevski wrote:
On MSVC, the following correct code produces error C2896: 'void operator ||(T,void (__cdecl *)(tag<X>))' : cannot use function template 'void bar(tag<X>)' as a function argument.
struct foo { };
template <int X> struct tag { };
template <int X> void bar( tag<X> ) { }
template <class T,int X> void operator||(T, void(*)(tag<X>)) { }
int main() { foo()||bar<1>; }
My goal is to have an operator|| overload that deduces tag<X> implicitly, but without using parenthesis, that is, foo()||bar<1>() wouldn't be satisfactory. Doesn't seem possible, but still I decided to ask. Any ideas?
Does putting an address-of operator in front of bar help?: foo()||&bar<1>; I don't have msvc handy to try it. -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.9 (GNU/Linux) iEYEARECAAYFAkqzgZcACgkQ5vihyNWuA4UMGwCg0GRNNW8IY6r0Vv1pxho+wLDt aYIAn02VTX7HrJZuxTzby+QsgKl2XVKw =G5Nh -----END PGP SIGNATURE-----
participants (6)
-
Emil Dotchevski
-
Emil Dotchevski
-
Frank Mori Hess
-
Jeffrey Hellrung
-
Steven Watanabe
-
Stewart, Robert