When T
is double(float)const
I get this error when I try to use function<T>
.
implicit instantiation of undefined template 'std::function<double (float) const>'
But it's OK when T
is double(float)
. I tried to use std:: remove_cv<T>::type
to remove this const
, but that doesn't work. And yes, I have #include<functional>
.
So my main question is: How to fix this and remove const
so that I can put this function type into std:: function
.?
I came across this issue when working with the operator()
method of lambdas, but I think this question is generally about any method type, not just for lambdas
But my second question is: What does double(float)const
even mean ?!! I can understand
double (ClassName::) (float) const
as it means the member function cannot modify its ClassName
object. When I put this type into a template to remove the class type, then I get the double(float)const
which is causing trouble.
template<typename>
struct DropClassType;
template<typename Sig, typename C>
struct DropClassType<Sig (C::*)> {
typedef Sig type_without_class;
};
(clang 3.4.2. The errors from g++-4.9.1 are more cryptic, but basically the same)
Why did I get the "implicit instantiation of undefined template" error?
std::function
is defined as an undefined base template and a partial specialization that matches "normal" function types (§20.9.11.2 [func.wrap.func]):
template<class> class function; // undefined
template<class R, class... ArgTypes>
class function<R(ArgTypes...)> { /* ... */ };
double (float) const
doesn't match R(ArgTypes...)
, so you get the undefined base template instead.
How to fix this and remove const so that I can put this function type into
std::function
?
The standard partial specialization trick. While we are at it, let's also remove volatile
.
template<class> class rm_func_cv; // undefined
template<class R, class... ArgTypes>
class rm_func_cv<R(ArgTypes...)> { using type = R(ArgTypes...); };
template<class R, class... ArgTypes>
class rm_func_cv<R(ArgTypes...) const> { using type = R(ArgTypes...); };
template<class R, class... ArgTypes>
class rm_func_cv<R(ArgTypes...) volatile> { using type = R(ArgTypes...); };
template<class R, class... ArgTypes>
class rm_func_cv<R(ArgTypes...) const volatile> { using type = R(ArgTypes...); };
Similar tricks can be used to remove ref-qualifiers, of course.
What does
double (float) const
even mean ?!!
This is a rather obscure corner of the standard (§8.3.5 [dcl.fct]/p6):
A function type with a cv-qualifier-seq or a ref-qualifier (including a type named by typedef-name (7.1.3, 14.1)) shall appear only as:
- the function type for a non-static member function,
- the function type to which a pointer to member refers,
- the top-level function type of a function typedef declaration or alias-declaration,
- the type-id in the default argument of a type-parameter (14.1), or
- the type-id of a template-argument for a type-parameter (14.3.1).
[ Example:
typedef int FIC(int) const; FIC f; // ill-formed: does not declare a member function struct S { FIC f; // OK }; FIC S::*pm = &S::f; // OK
—end example ]
In short, it's basically "half a type" that you can use to declare a class member function or a pointer-to-member type (or pass as a template parameter).
#include <functional>
template <typename T>
struct function_remove_const;
template <typename R, typename... Args>
struct function_remove_const<R(Args...)>
{
using type = R(Args...);
};
template <typename R, typename... Args>
struct function_remove_const<R(Args...)const>
{
using type = R(Args...);
};
int main()
{
std::function<function_remove_const<double(float)const>::type> f;
}
Live demo link.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With