I observed some inconsistency between two compilers (g++ 4.5, VS2010 RC) in the way they match lambdas with partial specializations of class templates. I was trying to implement something like boost::function_types for lambdas to extract type traits. Check this for more details.
In g++ 4.5, the type of the operator() of a lambda appears to be like that of a free standing function (R (*)(…)) whereas in VS2010 RC, it appears to be like that of a member function (R (C::*)(…)). So the question is are compiler writers free to interpret any way they want? If not, which compiler is correct? See the details below.
template <typename T>
struct function_traits
: function_traits<decltype(&T::operator())>
{
// This generic template is instantiated on both the compilers as expected.
};
template <typename R, typename C>
struct function_traits<R (C::*)() const> { // inherits from this one on VS2010 RC
typedef R result_type;
};
template <typename R>
struct function_traits<R (*)()> { // inherits from this one on g++ 4.5
typedef R result_type;
};
int main(void) {
auto lambda = []{};
function_traits<decltype(lambda)>::result_type *r; // void *
}
This program compiles on both g++ 4.5 and VS2010 but the function_traits that are instantiated are different as noted in the code.
I believe that GCC is noncompliant.N3092 §5.1.2/5 saysSo while many things about the closure object’s type are implementation-defined, the function itself must be a member to be
publicand must be a nonstatic member to beconst.EDIT: This program indicates that
operator()is a member function on GCC 4.6, which is essentially the same as 4.5.output:
EDIT: It looks like the only problem is that pointers to certain closure call operators fail to match ptmf template patterns. The workaround is to declare the lambda expression
mutable. This is meaningless if there is no capture and only (aside from fixing the problem) seems to change the const-ness of the call operator.output:
Without the mutable and with the const,
spectfundoes not print signatures for either of the last two queries.