在CRTP中推断模板成员函数的返回类型 [英] Inferring return type of templated member functions in CRTP
问题描述
是否可以推断CRTP基类中模板成员函数的返回类型?
,它返回类型失败。考虑下面的例子。
While inferring argument types works well, it fails with the return type. Consider the example below.
#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.
我直观的假设是,如果编译器能够推断类型 int
为 f
的参数,它也应该用于返回 bool
,因为两种类型在模板实例化时间是已知的。
My intuitive assumption is that if the compiler is capable of inferring type int
for the argument to f
, it should also work for the return bool
, because both types are known at template instantiation time.
我尝试使用尾随返回类型函数语法,但后来找不到一个工作表达式放在 decltype
I tried using the trailing return type function syntax, but then failed to find a working expression to put in decltype
.
对于函数有一个或多个模板参数,DietmarKühl提供了一个基于延迟使用间接层模板实例化的解决方案。不幸的是,当基类函数没有任何参数时,这不起作用,像这样:
For the case where the function has one or more templated arguments, Dietmar Kühl provided a solution based on delaying template instantiation using on layer of indirection. Unfotunately, this does not work when a base class function does not have any argument, like this:
template <typename R>
R g()
{
return static_cast<Derived&>(*this).g_impl();
}
尝试使用相同的技术失败,因为不存在依赖类型。如何处理这种情况?
Attempts to use the same technique fail because there exist no dependent types. How does one handle this case?
正如Johannes Schaub指出的,C ++ 11功能默认模板参数,所以总是可以使 g
依赖于任意类型,然后应用Dietmar的解决方案:
As pointed out by Johannes Schaub, C++11 features default template arguments, so it is always possible to make g
dependent on an arbitrary type and then apply Dietmar's solution:
template <typename T = void>
auto g() -> typename g_impl_result<Derived, T>::type
{
return static_cast<Derived&>(*this).g_impl();
}
EDIT 3
这个问题在C ++ 14中不存在,因为我们对正常函数有返回类型的扣除,允许我们简单写:
EDIT 3
This problem does not exist in C++14 anymore, since we have return type deduction for normal functions, allowing us to write simply:
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;
}
};
推荐答案
额外的间接是你的朋友:
An extra indirection is your friend:
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);
}
};
这篇关于在CRTP中推断模板成员函数的返回类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!