decltype(auto),尾随 return 类型和 sfinae:我们可以混合使用它们吗?
decltype(auto), trailing return type and sfinae: can we mix them?
考虑以下代码:
auto f() -> decltype(auto) { /* do whatever you want here */ }
int main() { f(); }
推导出return类型,decltype(auto)
用作尾随return类型。
下面的代码是稍微修改过的(实际上是sfinae'd)的版本:
struct S { static void f() {} };
struct T {};
template<typename U>
auto f(int) -> decltype(U::f(), void()) {
// do whatever you want here
}
template<typename>
auto f(char) -> decltype(auto) {
// do whatever you want here
}
int main() {
f<S>(0);
f<T>(0);
}
如果你参加考试这个功能:
template<typename U>
auto f(int) -> decltype(U::f(), void()) {
// do whatever you want here
}
问题是:是否可以使用尾部 return 类型来执行 sfinae 并且仍然推导出 return 类型?
我的意思是类似于下面的代码(当然不起作用):
template<typename U>
auto f(int) -> decltype(U::f(), auto) {
// do whatever you want here
}
注意:我不是在寻找涉及模板参数的替代方法,我知道它们,我只是想知道 this 是否是一个可行的解决方案。
decltype(auto)
是一个不可分割的结构(几乎就像 decltype_auto
这样的关键字)。除此之外,auto
不能用作 decltype(x)
中的独立实体,因为那样会阻止 x
成为有效的表达式。
不是答案,而是使用 void_t 的可能解决方法。
至少它和你想做的一样干:
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
struct S { static int f() { return 3; } };
struct P { static int p() { return 4; } };
struct T {};
template<typename U, void_t<decltype(U::f())>* = nullptr >
auto f(int) -> decltype(auto)
{
// do whatever you want here
std::cout << "f1\n";
return U::f();
}
template<typename U, void_t<decltype(U::p())>* = nullptr >
auto f(int) -> decltype(auto)
{
// do whatever you want here
std::cout << "f3\n";
return U::p();
}
template<typename>
auto f(char) -> decltype(auto) {
std::cout << "f2\n";
// do whatever you want here
}
int main() {
std::cout << f<S>(0) << '\n';
std::cout << f<P>(0) << '\n';
f<T>(0);
}
您可以向该函数添加另一个 void(*)()
类型的参数,并将尾随 return 类型的 lambda 作为默认参数分配给它,以便可以通过 lambda 应用 SFINAE:
template<typename U>
decltype(auto) f(int, void(*)() = []()->decltype(U::f(), void()) {})
{
// do whatever you want here
}
考虑以下代码:
auto f() -> decltype(auto) { /* do whatever you want here */ }
int main() { f(); }
推导出return类型,decltype(auto)
用作尾随return类型。
下面的代码是稍微修改过的(实际上是sfinae'd)的版本:
struct S { static void f() {} };
struct T {};
template<typename U>
auto f(int) -> decltype(U::f(), void()) {
// do whatever you want here
}
template<typename>
auto f(char) -> decltype(auto) {
// do whatever you want here
}
int main() {
f<S>(0);
f<T>(0);
}
如果你参加考试这个功能:
template<typename U>
auto f(int) -> decltype(U::f(), void()) {
// do whatever you want here
}
问题是:是否可以使用尾部 return 类型来执行 sfinae 并且仍然推导出 return 类型?
我的意思是类似于下面的代码(当然不起作用):
template<typename U>
auto f(int) -> decltype(U::f(), auto) {
// do whatever you want here
}
注意:我不是在寻找涉及模板参数的替代方法,我知道它们,我只是想知道 this 是否是一个可行的解决方案。
decltype(auto)
是一个不可分割的结构(几乎就像 decltype_auto
这样的关键字)。除此之外,auto
不能用作 decltype(x)
中的独立实体,因为那样会阻止 x
成为有效的表达式。
不是答案,而是使用 void_t 的可能解决方法。
至少它和你想做的一样干:
template<typename... Ts> struct make_void { typedef void type;};
template<typename... Ts> using void_t = typename make_void<Ts...>::type;
struct S { static int f() { return 3; } };
struct P { static int p() { return 4; } };
struct T {};
template<typename U, void_t<decltype(U::f())>* = nullptr >
auto f(int) -> decltype(auto)
{
// do whatever you want here
std::cout << "f1\n";
return U::f();
}
template<typename U, void_t<decltype(U::p())>* = nullptr >
auto f(int) -> decltype(auto)
{
// do whatever you want here
std::cout << "f3\n";
return U::p();
}
template<typename>
auto f(char) -> decltype(auto) {
std::cout << "f2\n";
// do whatever you want here
}
int main() {
std::cout << f<S>(0) << '\n';
std::cout << f<P>(0) << '\n';
f<T>(0);
}
您可以向该函数添加另一个 void(*)()
类型的参数,并将尾随 return 类型的 lambda 作为默认参数分配给它,以便可以通过 lambda 应用 SFINAE:
template<typename U>
decltype(auto) f(int, void(*)() = []()->decltype(U::f(), void()) {})
{
// do whatever you want here
}