从成员函数类型中去除const的特性?

9
Tdouble(float)const 时,我在尝试使用 function<T> 时遇到了这个错误。
implicit instantiation of undefined template 'std::function<double (float) const>'

但当T为double(float)时,这没关系。我尝试使用std::remove_cv::type来移除这个const,但是不起作用。是的,我已经包含了#include。
所以我的主要问题是:如何修复并删除const,以便我可以将此函数类型放入std :: function中?
在处理lambda的operator()方法时,我遇到了这个问题,但我认为这个问题通常适用于任何方法类型,而不仅仅是lambda。
但我的第二个问题是:double(float)const甚至是什么意思?! 我可以理解
double (ClassName::) (float) const

这意味着成员函数不能修改其 ClassName 对象。当我将此类型放入模板中以删除类类型时,我得到了 double(float)const,这可能会引起麻烦。

template<typename>
struct DropClassType;
template<typename Sig, typename C>
struct DropClassType<Sig (C::*)> {
  typedef Sig type_without_class;
};

(clang 3.4.2。来自 g++-4.9.1 的错误更加神秘,但本质上相同)
2个回答

10
为什么我收到了“隐式实例化未定义模板”的错误提示? std::function被定义为一个未定义的基础模板以及与“普通”函数类型匹配的部分特化(§20.9.11.2 [func.wrap.func]):
template<class> class function; // undefined
template<class R, class... ArgTypes>
class function<R(ArgTypes...)>  { /* ... */ };

double (float)R(ArgTypes...) 不匹配,所以您会得到未定义的基础模板。


如何修复并删除 const,以便我可以将此函数类型放入 std::function 中?

使用标准的部分特化技巧。顺便也删除 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...); };

当然,类似的技巧也可以用来删除ref-qualifiers


double (float) const到底是什么意思?!!

这是标准的一个相对晦涩的角落(§8.3.5 [dcl.fct]/p6):

带有cv-qualifier-seqref-qualifier的函数类型(包括由typedef-name(7.1.3、14.1)命名的类型)只能出现在下列情况中:

  • 非静态成员函数的函数类型,
  • 成员指针所引用的函数类型,
  • 函数typedef声明或别名声明的顶层函数类型,
  • type-parameter(14.1)的默认参数的type-id,或
  • 模板参数(14.3.1)的type-parametertype-id

[例子]:

    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

简单来说,它基本上是“半类型”,可以用于声明类成员函数、指向成员的指针类型(或作为模板参数传递)。

示例结束]


很好。因此,它本身并没有什么意义,但是当与类重新关联时,就可以再次变得有意义,就像你给出的两个例子一样。是否有一种标准特性可以去除const? - Aaron McDaid
@AaronMcDaid 我不知道有没有相关的内容。这个问题比较晦涩,我怀疑没有人会想到为此编写一个特性。 - T.C.
1
我认为这将来会更加清晰,这要归功于lambda表达式。这使我能够编写一个函数,它将接受任何(非通用)lambda表达式或类似对象,并自动将其转换为std::function对象。只需在lambda表达式上运行decltype(&T::operator()),就会返回一个类型,但需要从该类型中删除类类型和奇怪的const。谢谢! - Aaron McDaid

6
#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;
}

现场演示链接。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接