Re: decltype within template specialization expression: legal?
Am 27.07.2011 01:53, schrieb Noah Roberts:
In trying to devise a way to check if a type has a function that can be
called with a set of argument types I came up with this:
template < bool B >
struct bool_
{
enum { value = B };
typedef bool_<B> type;
};
template < typename T
, typename E = int >
struct has_fun : bool_<false> {};
template < typename T > T&& declval(); // MSVC ommision
template < typename T >
struct has_fun< T, decltype(declval<T>().fun(declval<int>()))> // error
: bool_<true>
{};
struct test
{
template < typename T >
int fun(T) { return 42; }
};
int main()
{
static_assert(has_fun<test>::value, "FAIL!");
}
Whether or not I use the specialization, I get the error:
error C2228: left of '.fun' must have class/struct/union
type is 'T'
This looks like a compiler defect to me. According to
[temp.class.spec.match] p2:
"A partial specialization matches a given actual template argument list
if the template arguments of the partial specialization can be deduced
from the actual template argument list (14.8.2)."
The reference to [temp.deduct] makes pretty clear, that via p8:
"If a substitution results in an invalid type or expression, type
deduction fails. An invalid type or expression is one that would be
ill-formed if written using the substituted arguments."
this deduction attempt should fail silently (if at all).
On the other hand, I can write the metafunction like so:
template < typename T >
struct has_callable_f
{
typedef char (&no) [1];
typedef char (&yes) [2];
template < typename S >
static yes check(decltype(declval<S>().fun(declval<int>())) *);
template < typename S >
static no check(...);
enum { value = sizeof(check<T>(nullptr)) == sizeof(yes) };
};
and this works fine.
The question I have, should the first have worked?
I believe it should have.
HTH & Greetings from Bremen,
- Daniel Kr?gler
--
[ See http://www.gotw.ca/resources/clcm.htm for info about ]
[ comp.lang.c++.moderated. First time posters: Do this! ]