如何在返回语句中以可移植的方式为复制列表init编写SFINAE

How do I write SFINAE for copy-list-init in a return statement, in a portable way?

本文关键字:复制 方式 列表 init SFINAE 编写 可移植 返回 语句      更新时间:2024-09-22

我正在尝试使以下函数SFINAE友好:

#include <utility>
template <typename T, typename ...P>
T foo(P &&... params)
{
return {std::forward<P>(params)...};
}

我不能将return语句放在SFINAE上下文中,但由于这是复制列表初始化的一个示例,我想我可以找到一个不同的可以使用SFINAE的示例。

T({...}),但只有GCC接受它:

template <typename T, typename ...P>
T foo(P &&... params)
requires requires{T({std::forward<P>(params)...});}
{
return {std::forward<P>(params)...};
}
#include <array>
struct A
{
A(int) {}
A(const A &) = delete;
A &operator=(const A &) = delete;
};
int main()
{
foo<std::array<A, 3>>(1, 2, 3); // Error: call to implicitly-deleted copy constructor of `std::array`.
}

还有foo({...})(一个函数调用(。GCC和Clang接受,但MSVC拒绝:

template <typename T>
void accept(T) noexcept;
template <typename T, typename ...P>
T foo(P &&... params)
requires requires{accept<T>({std::forward<P>(params)...});}
{
return {std::forward<P>(params)...};
}

我如何解决编译器错误,并以可移植的方式编写这个SFINAE?

如果在accept:中使用const&参数,则第二个版本有效

template <typename T>
void accept(const T&) noexcept;