gpt4 book ai didi

c++ - 成员函数中的 decltype(auto) 忽略无效主体,decltype(expr) 失败

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:28:21 25 4
gpt4 key购买 nike

我有一个简单的模板化包装器结构,其成员函数在其模板类型的对象上调用 .error()

template <typename T>
struct Wrapper {
T t;
decltype(auto) f() {
return t.error(); // calls .error()
}
};

如果我用一个没有 error() 成员函数的类型实例化它,只要我不调用它就没问题。这就是我想要的行为。

Wrapper<int> w; // no problem here
// w.error(); // uncommented causes compilation failure

如果我使用我认为是具有尾随返回类型的语义等价物,它会在变量声明上出错

template <typename T>
struct Wrapper {
T t;
auto f() -> decltype(t.error()) {
return t.error();
}
};

Wrapper<int> w; // error here

我承认这两者在语义上并不等价,但是无论如何可以使用尾随返回类型(仅限 C++11)来获得前者的行为,而不需要使用某种 来专门化整个类HasError tmp 欺骗?

最佳答案

版本之间的区别

decltype(auto) f();
auto f() -> decltype(t.error());

是第二个函数声明可以无效。函数模板的返回类型推导发生在定义被实例化[dcl.spec.auto]/12时。虽然我找不到任何有关类模板成员函数的返回类型推导的信息,但我认为它们的行为相似。

隐式实例化类模板 Wrapper 会导致实例化声明,但不会实例化所有(非虚拟)的定义成员函数[temp.inst]/1。声明 decltype(auto) f(); 有一个非推导的占位符但有效。另一方面,auto f() -> decltype(t.error()); 对于某些实例化有无效的返回类型。


C++11 中的一个简单解决方案是推迟确定返回类型,例如通过将 f 转换为函数模板:

template<typename U = T>
auto f() -> decltype( std::declval<U&>().error() );

不过,该函数的定义让我有点担心:

template<typename U = T>
auto f() -> decltype( std::declval<U&>().error() )
{
return t.error();
}

对于 Wrapper 的特殊化,其中 t.error() 无效,上面的 f 是一个函数模板,不能产生有效的专长。这可能属于 [temp.res]/8,它表示此类模板格式错误,无需诊断:

If no valid specialization can be generated for a template, and that template is not instantiated, the template is ill-formed, no diagnostic required.

但是,我怀疑该规则已引入允许,但不要求实现检查非实例化模板中的错误。在这种情况下,源代码中没有编程错误;该错误将发生在源代码描述的类模板的实例化中。所以,我觉得应该没问题。


另一种解决方案是使用后备返回类型使函数声明格式正确,即使定义不是(对于所有实例化):

#include <type_traits>

template<typename T> struct type_is { using type = T; };

template <typename T>
struct Wrapper {
T t;

template<typename U=T, typename=void>
struct error_return_type_or_void : type_is<void> {};

template<typename U>
struct error_return_type_or_void
<U, decltype(std::declval<U&>().error(), void())>
: type_is<decltype(std::declval<U&>().error())> {};

auto f() -> typename error_return_type_or_void<>::type {
return t.error();
}
};

关于c++ - 成员函数中的 decltype(auto) 忽略无效主体,decltype(expr) 失败,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29463711/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com