C++Talk.NET Forum Index C++Talk.NET
C++ language newsgroups
 
Archives   FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

enable_if and operator[] (or workaround)

 
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated)
View previous topic :: View next topic  
Author Message
Michael Fawcett
Guest





PostPosted: Tue Oct 19, 2004 4:23 pm    Post subject: enable_if and operator[] (or workaround) Reply with quote



The following is producing a compiler error with MSVS 7.1 :

template <typename X, typename Y = X, typename Z = Y>
struct vec3
{
// operator[] will only be enabled if the typex == typey == typez
inline typename boost::enable_if<boost::mpl::and_ boost::is_same<Y, Z> >, X &>::type operator[](size_t idx);
inline typename boost::enable_if<boost::mpl::and_ boost::is_same<Y, Z> >, X const &>::type operator[](size_t idx) const;

};

int main(void)
{
vec3<float, int> a;
}

vec3_class.h(50): error C2039: 'type' : is not a member of
'boost::enable_if<Cond,T>'
with
[

Cond=boost::mpl::and_<boost::is_same,
T=float &
]


which would suggest that the compiler is doing more than just a syntax check
of the declaration. It's been a while since I've used enable_if, but isn't
this legal usage? Shouldn't I only get a compiler error if I attempt to use
operator[] with a class where X != Y or Y != Z?

Apologies if this should have gone to the boost mailing list.

Thanks,

Michael Fawcett



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Maxim Yegorushkin
Guest





PostPosted: Wed Oct 20, 2004 9:40 pm    Post subject: Re: enable_if and operator[] (or workaround) Reply with quote



On 19 Oct 2004 12:23:20 -0400, Michael Fawcett <spam_mikef (AT) intelgames (DOT) com>
wrote:

Quote:
The following is producing a compiler error with MSVS 7.1 :
template <typename X, typename Y = X, typename Z = Y
struct vec3
{
// operator[] will only be enabled if the typex == typey == typez
inline typename boost::enable_if boost::is_same<Y, Z> >, X &>::type operator[](size_t idx);
inline typename boost::enable_if<boost::mpl::and_ boost::is_same<Y, Z> >, X const &>::type operator[](size_t idx) const;
};

The compiler is right.

SFINAE applies to function templates only. Here you've got a class template
with member functions and with no function templates. And these member
functions have ill-formed signatures when vec3's template arguments are not
of the same type.

--
Maxim Yegorushkin

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Peter Dimov
Guest





PostPosted: Wed Oct 20, 2004 9:43 pm    Post subject: Re: enable_if and operator[] (or workaround) Reply with quote



"Michael Fawcett" <spam_mikef (AT) intelgames (DOT) com> wrote

Quote:
The following is producing a compiler error with MSVS 7.1 :

template <typename X, typename Y = X, typename Z = Y
struct vec3
{
// operator[] will only be enabled if the typex == typey == typez
inline typename boost::enable_if boost::is_same<Y, Z> >, X &>::type operator[](size_t idx);
inline typename boost::enable_if<boost::mpl::and_ boost::is_same<Y, Z> >, X const &>::type operator[](size_t idx) const;

};

int main(void)
{
vec3<float, int> a;
}

vec3_class.h(50): error C2039: 'type' : is not a member of
'boost::enable_if<Cond,T>'
with

[

Cond=boost::mpl::and_<boost::is_same,
T=float &
]


which would suggest that the compiler is doing more than just a syntax check
of the declaration. It's been a while since I've used enable_if, but isn't
this legal usage?

No, it's not. enable_if/SFINAE only works with function templates.
Your operator[] functions are ordinary member functions. They are
members of a class template, but this doesn't turn them into function
templates, and their declarations are instantiated when the definition
of their enclosing class template is instantiated. Their _definitions_
will only be instantiated upon first use, though, so you can put a
static assert inside.

HTH.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Motti Lanzkron
Guest





PostPosted: Thu Oct 21, 2004 5:11 pm    Post subject: Re: enable_if and operator[] (or workaround) Reply with quote

Michael Fawcett wrote:
Quote:
The following is producing a compiler error with MSVS 7.1 :

template <typename X, typename Y = X, typename Z = Y
struct vec3
{
// operator[] will only be enabled if the typex == typey == typez
inline typename boost::enable_if boost::is_same<Y, Z> >, X &>::type operator[](size_t idx);
inline typename boost::enable_if<boost::mpl::and_ boost::is_same<Y, Z> >, X const &>::type operator[](size_t idx) const;

};

The way I understand things SFINAE only kicks in when selecting
between template functions, if the only option has substitution
failure that you get SFIAE [Substitution Failure Is An Error ;o)].

Maybe what you want is to inherit from a base class that either has or
doesn't have the required function.

Something like this.

template <class Derived, typename X, typename Y, typename Z>
struct vec3_helper {
// they differ no operator[]
};

template <class Derived, typename X>
struct vec3_helper<X, X, X>
{
// they're the same supply operator[]
A& operator[](size_t) {
// do stuff on static_cast<Derived*>(this)
}
A operator[](size_t) const;
};


Then you use:
template <typename X, typename Y = X, typename Z = Y>
struct vec3 : public vec3_helper<vec3, X, Y, Z>
{
};


Good luck.

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
James Hopkin
Guest





PostPosted: Thu Oct 21, 2004 5:16 pm    Post subject: Re: enable_if and operator[] (or workaround) Reply with quote

"Michael Fawcett" <spam_mikef (AT) intelgames (DOT) com> wrote

Quote:

It's been a while since I've used enable_if, but isn't
this legal usage? Shouldn't I only get a compiler error if I attempt to use
operator[] with a class where X != Y or Y != Z?


No, it only works for template functions, where the types are being
deduced. This is somewhat similar to a recent discussion:

<tinyurl.com/6xgsw>


James

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
David Abrahams
Guest





PostPosted: Thu Oct 21, 2004 5:31 pm    Post subject: Re: enable_if and operator[] (or workaround) Reply with quote

"Michael Fawcett" <spam_mikef (AT) intelgames (DOT) com> wrote

Quote:
The following is producing a compiler error with MSVS 7.1 :

template <typename X, typename Y = X, typename Z = Y
struct vec3
{
// operator[] will only be enabled if the typex == typey == typez
inline typename boost::enable_if boost::is_same<Y, Z> >, X &>::type operator[](size_t idx);
inline typename boost::enable_if<boost::mpl::and_ boost::is_same<Y, Z> >, X const &>::type operator[](size_t idx) const;

};

int main(void)
{
vec3<float, int> a;
}

vec3_class.h(50): error C2039: 'type' : is not a member of
'boost::enable_if<Cond,T>'
with
[

Cond=boost::mpl::and_<boost::is_same,
T=float &
]


which would suggest that the compiler is doing more than just a syntax check
of the declaration. It's been a while since I've used enable_if, but isn't
this legal usage? Shouldn't I only get a compiler error if I attempt to use
operator[] with a class where X != Y or Y != Z?

The problem is that those operator[] *declarations* are instantiated
with the class. SFINAE only works on functions that are templated.
Non-templated member functions' definitions are instantiated only on
demand, but at the point the class is instantiated the types are all
determined, so type errors in the signatures of the functions count.

Quote:
Apologies if this should have gone to the boost mailing list.

It should have. Why don't you post there?

HTH,
Dave
--
David Abrahams
Boost Consulting
http://www.boost-consulting.com

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
Michael Fawcett
Guest





PostPosted: Fri Oct 22, 2004 5:18 pm    Post subject: Re: enable_if and operator[] (or workaround) Reply with quote

"Peter Dimov" <pdimov (AT) gmail (DOT) com> wrote

Quote:
"Michael Fawcett" <spam_mikef (AT) intelgames (DOT) com> wrote in message
news:<cl1isj$50u$1 (AT) gateway (DOT) northropgrumman.com>...
The following is producing a compiler error with MSVS 7.1 :

code snipped

which would suggest that the compiler is doing more than just a syntax
check
of the declaration. It's been a while since I've used enable_if, but
isn't
this legal usage?

No, it's not. enable_if/SFINAE only works with function templates.
Your operator[] functions are ordinary member functions. They are
members of a class template, but this doesn't turn them into function
templates, and their declarations are instantiated when the definition
of their enclosing class template is instantiated. Their _definitions_
will only be instantiated upon first use, though, so you can put a
static assert inside.

HTH.

Yes of course, thank you. I actually just read a section of "C++ Templates"
that told me exactly what you have suggested.

-Michael Fawcett



[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]

Back to top
kwikius
Guest





PostPosted: Mon Oct 25, 2004 1:44 pm    Post subject: Re: enable_if and operator[] (or workaround) Reply with quote

"Michael Fawcett" <spam_mikef (AT) intelgames (DOT) com> wrote

Quote:
The following is producing a compiler error with MSVS 7.1 :

template <typename X, typename Y = X, typename Z = Y
struct vec3
{
// operator[] will only be enabled if the typex == typey == typez
inline typename
boost::enable_if boost::is_same<Y, Z> >, X &>::type operator[](size_t idx);
inline typename
boost::enable_if<boost::mpl::and_ boost::is_same<Y, Z> >, X const &>::type operator[](size_t idx) const;

};

int main(void)
{
vec3<float, int> a;
}

BTW assume should be eg vec3<float, float> a; above

Of course the problem is not insurmountable:

template <typename X, typename Y = X, typename Z = Y>
struct vec3
{
// operator[] will only be enabled if the typex == typey == typez

template <typename IDX>
inline
typename boost::enable_if<
boost::mpl::and_<
boost::is_same boost::is_same<Y, Z>,
boost::is_convertible<IDX,size_t>
Quote:
,
X &
::type operator[](IDX idx);

template <typename IDX>
inline
typename boost::enable_if<
boost::mpl::and_<
boost::is_same boost::is_same<Y, Z>,
boost::is_convertible<IDX,size_t>
Quote:
,
X const &
::type operator[](IDX idx)const;

};

should work ok

regards
Andy Little

[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]


Back to top
Display posts from previous:   
Post new topic   Reply to topic    C++Talk.NET Forum Index -> C++ Language (Moderated) All times are GMT
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum


Powered by phpBB © 2001, 2006 phpBB Group
SEO toolkit © 2004-2006 webmedic.