推断CRTP中模板化成员函数的返回类型
Inferring return type of templated member functions in CRTP
是否可以推断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
对于函数具有一个或多个模板化参数的情况,Dietmar Kü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);
}
};
相关文章:
- 对RValue对象调用的LValue ref限定成员函数
- 为什么使用 "this" 指针调用派生成员函数?
- 将公共但非静态的成员函数与ALGLIB集成
- 使用指向成员的指针将成员函数作为参数传递
- 将重载的成员函数传递给函数模板
- 我不小心调用了一个没有自己类对象的成员函数.但这是怎么回事呢
- 如何在C++中使用非静态成员函数作为回调函数
- C++错误C2600:无法定义编译器生成的特殊成员函数(必须首先在类中声明)
- 关联容器的下界复杂性:成员函数与非成员函数
- 在 C++ 中用派生类型重写成员函数
- 链表的泛型函数remove()与成员函数remove)
- 如何将lambda作为模板类的成员函数参数
- constexpr构造函数需要常量成员函数时出现问题
- 将自由函数绑定为类成员函数
- 区分非成员函数和头文件中的成员函数
- 如何从子成员函数修改父公共成员变量
- 保留对其他类的成员函数的引用
- 在运算符重载定义中使用成员函数(const错误)
- 内联如何影响模块接口中的成员函数
- 将成员函数指针作为参数传递给模板方法