【问题标题】:Clang can't find template binary operator in fold expressionClang 在折叠表达式中找不到模板二元运算符
【发布时间】:2018-01-16 02:31:08
【问题描述】:

这是我连接元组的二元运算符:

template <class... Args1, class... Args2>
constexpr decltype(auto) operator+(const std::tuple<Args1...> &tup1,
                                   const std::tuple<Args2...> &tup2) {
   return std::tuple_cat(tup1, tup2);
}

它在带有两个元组的编译器(gcc、clang)上都能完美运行:

template <class Arg1, class Arg2>
constexpr decltype(auto) concat_test(Arg1 &&arg1, Arg2 &&arg2) {
   return arg1 + arg2;
}

但是当我尝试在折叠表达式中使用它时,如下所示:

template <class... Args>
constexpr decltype(auto) multiple_concat(Args &&... args) {
   return (args + ...);
}

gcc 7.1.1 编译它没有任何错误,不像 clang 5.0,它会产生错误输出:

错误:调用函数“operator+”在模板定义中既不可见,也不通过参数相关查找找到

return (args + ...);

注意:在此处请求的函数模板特化 'multiple_concat ' 的实例化中

multiple_concat(tup1, tup2);

注意:'operator+' 应该在调用站点之前声明

constexpr decltype(auto) 运算符+(const std::tuple &tup1, const std::tuple &tup2)

这段代码格式不正确,clang 到底在说什么?

【问题讨论】:

  • clang 4.0.1 编译它,clang 6.0 也是如此。这很可能是编译器错误。
  • @Rakete1111 my clang 4.0.1 (tags/RELEASE_401/final) 没有编译这个,还有 clang 6.0 Example
  • 我使用的是 xcode clang 9.0.0(大致相当于开源的 clang 4.0),它也无法编译。我自己在不同的环境中遇到了这个问题,这导致了我这篇文章。
  • 这能回答你的问题吗? fold expression and function name lookup

标签: c++ templates variadic-templates c++17


【解决方案1】:

2018 年 8 月:Xcode 9.0(大致相当于开源 clang 4.0)仍然无法编译此代码,而 g++ 可以正确完成这项工作。

我知道不能使用闪亮的新模板折叠语法很痛苦,但这里有一个基于if constexpr 的解决方法,这是我们可以使用的下一个最佳方法。

template <typename T, typename... Ts>
constexpr decltype(auto) multiple_concat(T&& arg, Ts&&... rest) {
    if constexpr (sizeof ...(rest) == 0) {
        return arg;
    }
    else {  // recursively concatenate the tuple
        return arg + multiple_concat(std::forward<Ts>(rest) ...);
    }
}

Clang 愉快地编译了这段代码。

【讨论】:

    【解决方案2】:

    显然,不合格的查找失败了。这使得它可以用 Clang 6 编译:

    namespace std {
        template <class... Args1, class... Args2>
        constexpr decltype(auto) operator+(const ::std::tuple<Args1...> &tup1,
                                           const ::std::tuple<Args2...> &tup2) {
          return ::std::tuple_cat(tup1, tup2);
        }
    
        template <class... Args1, class... Args2>
        constexpr decltype(auto) operator+(::std::tuple<Args1...> &&tup1,
                                           ::std::tuple<Args2...> &&tup2) {
          return ::std::tuple_cat(tup1, tup2);
        }
    }
    

    【讨论】:

      【解决方案3】:

      由于其他答案没有出来并说:代码很好。这是一个长期存在的Clangbug,影响版本到 11。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-04-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-10-11
        相关资源
        最近更新 更多