【问题标题】:Template constraints on operator overloading does not work as expected运算符重载的模板约束未按预期工作
【发布时间】:2022-12-18 07:45:51
【问题描述】:
#include <tuple>
#include <utility>

template<typename T>
struct is_tuple_like : std::false_type {};

template<typename... Ts>
struct is_tuple_like<std::tuple<Ts...>> : std::true_type {};

template<typename T, typename U>
struct is_tuple_like<std::pair<T, U>> : std::true_type {};

template<typename T>
concept tuple_like = is_tuple_like<T>::value;

template<tuple_like L, tuple_like R, int N = std::tuple_size_v<L>>
auto operator*(const L &lhs, const R &rhs) { return 0; }

enum { Enum };

int main()
{
    Enum * Enum; // causes compilation error
    return 0;
}

你可以在这里运行代码:http://coliru.stacked-crooked.com/a/f65e333060f40e60

我定义了一个概念,叫做tuple_like,并使用这个概念重载了operator*()

然后,如果我乘以 enums,我为 tuple_like 重载的 operator*() 被拾取并且编译器抱怨缺少 std::tuple_sizeenum

我在这里做错了什么以及如何在不为每个类模板超载的情况下修复它 - std::tuplestd::pair

仅供参考,即使它不寻常,我也无法删除乘以 enums 的部分,因为它不是我的代码。

【问题讨论】:

标签: c++ operator-overloading c++20 c++-concepts


【解决方案1】:

tuple_size_v 转换为tuple_size::value 以启用 SFINAE

template<tuple_like L, tuple_like R, int N = std::tuple_size<L>::value>
auto operator*(const L &lhs, const R &rhs) { return 0; }

但是,我看不到在此处声明额外的模板参数 N 有任何价值。满足tuple_like的类型已经保证了tuple_size_v是一个有效值。

N移到函数体中会更合适

template<tuple_like L, tuple_like R>
auto operator*(const L &lhs, const R &rhs) { 
  constexpr auto N = std::tuple_size_v<L>; // guaranteed to work
  // uses N below
}

【讨论】:

    【解决方案2】:

    看起来 gcc 无法为模板参数的默认值处理 SFINAE。此解决方法修复了它:

    template<tuple_like L, tuple_like R, int N>
    auto operator*(const L &lhs, const R &rhs) { return 0; }
    
    template<tuple_like L, tuple_like R>
    auto operator*(const L &lhs, const R &rhs) { return operator*<L, R, std::tuple_size_v<L>>(lhs, rhs); }
    
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-01-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-25
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多