加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c – 在CRTP中推送返回类型的模板成员函数

发布时间:2020-12-16 05:50:19 所属栏目:百科 来源:网络整理
导读:是否可以在CRTP基类中推断模板化成员函数的返回类型? 虽然推断参数类型工作正常,但它返回类型失败.请考虑下面的例子. #include iostreamtemplate typename Derivedstruct base{ template typename R,typename T R f(T x) { return static_castDerived(*this
是否可以在CRTP基类中推断模板化成员函数的返回类型?

虽然推断参数类型工作正常,但它返回类型失败.请考虑下面的例子.

#include <iostream>

template <typename Derived>
struct base
{
  template <typename R,typename T>
  R f(T x)
  {
    return static_cast<Derived&>(*this).f_impl(x);
  }
};

struct derived : base<derived>
{
  bool f_impl(int x)
  {
    std::cout << "f(" << x << ")" << std::endl;
    return true;
  }
};

int main()
{
  bool b = derived{}.f(42);
  return b ? 0 : 1;
}

这会产生以下错误:

bool b = derived{}.f(42);
           ~~~~~~~~~~^
crtp.cc:7:5: note: candidate template ignored: couldn't infer template argument 'R'
  R f(T x)
    ^
1 error generated.

我的直观假设是,如果编译器能够推断f的参数的类型int,那么它也应该用于返回bool,因为这两种类型在模板实例化时都是已知的.

我尝试使用尾随的返回类型函数语法,但是然后找不到一个工作表达式来放入decltype.

编辑1

对于函数具有一个或多个模板参数的情况,DietmarKühl提供了一种基于使用间接层延迟模板实例化的解决方案.不幸的是,当基类函数没有任何参数时,这不起作用,如下所示:

template <typename R>
R g()
{
  return static_cast<Derived&>(*this).g_impl();
}

尝试使用相同的技术失败,因为不存在依赖类型.如何处理这种情况?

编辑2

正如Johannes Schaub指出的那样,C 11具有默认的模板参数,因此总是可以使g依赖于任意类型,然后应用Dietmar的解决方案:

template <typename T = void>
auto g() -> typename g_impl_result<Derived,T>::type
{
  return static_cast<Derived&>(*this).g_impl();
}

编辑3

C 14中不存在这个问题,因为我们对正常的函数有返回类型的扣除,可以简单地写:

template <typename Derived>
struct base
{
  template <typename T>
  auto f(T x)
  {
    return static_cast<Derived&>(*this).f_impl(x);
  }

  auto g()
  {
    return static_cast<Derived&>(*this).g_impl();
  }
};

struct derived : base<derived>
{
  bool f_impl(int x)
  {
    return true;
  }

  double g_impl()
  {
    return 4.2;
  }
};

解决方法

一个额外的间接是你的朋友:
template <typename D,typename T>
struct f_impl_result
{
    typedef decltype(static_cast<D*>(0)->f_impl(std::declval<T>())) type;
};

template <typename Derived>
struct base
{
    template <typename T>
    auto f(T x) -> typename f_impl_result<Derived,T>::type
    {
        return static_cast<Derived&>(*this).f_impl(x);
    }
};

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读