Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
103 views
in Technique[技术] by (71.8m points)

c++ - trait to drop const from a member function type?

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)

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

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).


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...