【问题标题】:enable_if with return type for class member function具有类成员函数的返回类型的 enable_if
【发布时间】:2019-02-16 11:46:27
【问题描述】:

我正在尝试一种基于类模板参数专门化成员函数的方法,而不必在类上使用 SFINAE(并导致代码重复或创建另一个类)。

由于两个模板参数不能是可选的,并且参数enable_if在指南中不受欢迎,所以我尝试了(剩余的)以下2种方法:

template <bool boolean = true>
struct sample {
    constexpr typename std::enable_if<boolean, int>::type bool_check_return(
        int s) const noexcept {
        return s + 1;
    }
    constexpr typename std::enable_if<!boolean, int>::type bool_check_return(
        int s) const noexcept {
        return s;
    }

    template <typename std::enable_if<boolean, int>::type = 0>
    int bool_check_template(
        int s) const noexcept {
        return s + 1;
    }
    template <typename std::enable_if<!boolean, int>::type = 0>
    int bool_check_template(
        int s) const noexcept {
        return s;
    }
};

Godbolt link

乍一看,我似乎并不明白为什么返回类型 SFINAE 会给出以下关于“重载不适用于仅返回类型不同的函数”的错误。 SFINAE 应该只保证一份,而不是两份。

我在不知不觉中违反了标准的哪一部分?或者这是一个编译器错误?实际上,使用 if constexpr 在 C++17 中这不是问题(而且由于一种形式有效,我可以简单地选择那个)。

此错误存在于 C++11 到 C++17 中,因此编译器出错的可能性很低。

error: functions that differ only in their return type cannot be overloaded
    constexpr typename std::enable_if<!boolean, int>::type bool_check_return(
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
note: previous definition is here
    constexpr typename std::enable_if<boolean, int>::type bool_check_return(
              ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ^
1 error generated.

【问题讨论】:

  • 在这种简单的情况下,您可以改用if constexpr

标签: c++ enable-if


【解决方案1】:

这里没有涉及 SFINAE,因为 bool_check_return 本身不是模板。它们只是常规的重载函数,仅在返回类型上有所不同。制作模板可以通过只允许其中一个来解决问题:

template<bool enabled = boolean>
constexpr typename std::enable_if<enabled, int>::type bool_check_return(
    int s) const noexcept {
    return s + 1;
}

template<bool enabled = boolean>
constexpr typename std::enable_if<not enabled, int>::type bool_check_return(
    int s) const noexcept {
    return s;
}

【讨论】:

  • 我只是以稍微不同的方式尝试了这个。如果您只为第二个函数编写template &lt;bool enabled = not boolean&gt; ... enable_if&lt;enabled, int&gt;::type bool_check_return(注意not 在模板参数中而不是enablie_if 参数中),编译器会抛出一个错误,说明该函数已重新声明。为什么你的版本能绕过这个错误?
  • 跟这个有关系吗? en.cppreference.com/w/cpp/language/…
  • @MarcoMerlini 这些重载的返回类型不同。虽然默认模板参数不是模板签名的一部分。
【解决方案2】:

编译器是对的。在任何情况下,您都不能重载具有相同返回类型的两个函数,即使替换后只有一种返回类型有效。

来自[over.load]

某些函数声明不能​​重载:

  • 不能重载仅在返回类型、异常规范或两者方面不同的函数声明。
  • ...

这条规则也不例外。

【讨论】:

    猜你喜欢
    • 2023-04-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-02-16
    • 2014-02-21
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多