【问题标题】:enable_if and auto return type?enable_if 和自动返回类型?
【发布时间】:2019-04-15 18:41:43
【问题描述】:

我想使用 type_traits 是否通过 shared_ptr 重载。

struct A {
    A(int i) : x(i) {}
    int x;
};

int main()
{
    A a{4};
    auto b = std::make_shared<A>(7);
    A& c = a;
    A* d = b.get();
    A* e = &a;

    std::cout << getX(a) << std::endl;
    std::cout << getX(b) << std::endl;
    std::cout << getX(c) << std::endl;
    std::cout << getX(d) << std::endl;
    std::cout << getX(e) << std::endl;

    return 0;
}

这是一种解决方案,但存在返回类型必须预先定义的问题。

template <typename T>
typename std::enable_if_t<!boost::has_dereference<T>::value, int> getX(T t)
{
    return t.x;
}

template <typename T>
typename std::enable_if_t<boost::has_dereference<T>::value, int> getX(T t)
{
    return t->x;
}

但是使用下面的方法,我可以将返回类型设为auto,但它看起来有点笨拙。

template <typename T, typename std::enable_if_t<!boost::has_dereference<T>::value>* = nullptr>
auto getX(T t)
{
    return t.x;
}

template <typename T, typename std::enable_if_t<boost::has_dereference<T>::value>* = nullptr>
auto getX(T t)
{
    return t->x;
}

有没有一种方法可以使用第一种类型并且仍然得到返回类型auto

我不想指定A::x 的类型,所以auto 返回类型最好。第二种类型可以做到这一点,但感觉有点笨拙。

或者有更好的方法吗?谢谢。

【问题讨论】:

  • 如果使用std::enable_if的返回类型形式,则不能使用auto作为返回类型。也许decltype(t.x)
  • 选项 2 需要最少的维护。你可以使用它,然后当 C++20 出现时切换到摆脱笨重的概念。
  • 你应该看看这个帖子stackoverflow.com/questions/39552139/…
  • std::enable_if 通常很笨重,无论你决定把它放在哪里。带有匿名模板参数的版本对我来说似乎不那么笨重。你会得到一个很好的连续auto getX(T t) { return .x; },它清楚地告诉你函数的重要部分。
  • 我个人更喜欢基于标签调度的解决方案,而不是在这种情况下启用。如果您希望我整理示例代码,请告诉我。

标签: c++ typetraits enable-if


【解决方案1】:

如果您只想为不同的类型运行一两行不同的代码,那么constexpr if 让您无需使用enable_if 就可以做到这一点,并允许您使用自动返回类型推导。你可以把getX简化成

template <typename T>
auto getX(T t)
{
    if constexpr (boost::has_dereference<T>::value)
        return t->x;
    else
        return t.x;
}

这是可行的,因为未执行的路径被丢弃,因此在编译时只编译了真实路径。

【讨论】:

  • 我们的构建系统还没有到 C++17 :(
  • @Mochan Bummer。您应该在问题中添加可以使用的标准。由于 C++17 是当前标准,因此仅使用 C++ 标签本身意味着 C++17 之前的所有内容都可以。
  • 我认为这是解决我的问题@NathanOliver 的最优雅的解决方案。我会把它牢记在心,这样当我们有 C++17 时,我会做出改变。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-04-01
  • 1970-01-01
  • 1970-01-01
  • 2014-01-09
  • 2012-08-16
  • 2023-04-09
相关资源
最近更新 更多