这是我连接元组的二元运算符:
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+”,该函数在模板定义中不可见,也不能通过参数相关的查找找到
返回(args + ...);
注意:在此处请求的函数模板专业化“multiple_concat < std::__1::tuple &, std::__1::tuple &>”的实例化中
multiple_concat(tup1, tup2);
注意:“operator+”应在调用站点之前声明
constexpr decltype(auto) 运算符+(const std::tuple &tup1, const std::tuple &tup2)
这段代码格式错误吗?clang到底在说什么?
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 愉快地编译了这段代码。
显然,不合格的查找失败了。这个使它可以使用 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);
}
}