最小工作示例:
#include <array>
#include <iostream>
template <typename T> struct is_array : std::false_type {};
template <typename U, std::size_t N> struct is_array<std::array<U, N>> : std::true_type {};
template <typename T>
std::enable_if_t<is_array<std::decay_t<T>>::value>
do_something_prob(T&& arr, typename T::value_type mul) // `arr` becomes an rvalue?
{
for (auto && v : arr)
std::cout << v * mul << '\n';
}
template <
typename T,
typename ElemT = std::enable_if_t<is_array<std::decay_t<T>>::value, typename T::value_type>
>
void do_something_no_prob(T&& arr, ElemT mul)
{
for (auto && v : arr)
std::cout << v * mul << '\n';
}
int main()
{
auto arr = std::array<int, 3>{1, 2, 3};
do_something_prob(std::array<int, 3>{1, 2, 3}, 2);
// do_something_prob(arr, 2); // error message: 'std::array<int, 3>&' is not a class, struct, or union type'
do_something_no_prob(std::array<int, 3>{1, 2, 3}, 2);
do_something_no_prob(arr, 2);
}
我想要实现什么:实现一个接受两个参数的函数模板,(1)对任何数组类型的前向引用和(2)与数组元素相同类型的副本。
这是通过
do_something_no_prob
实现的。但do_something_prob
有什么问题呢?它无法处理左值。
引用没有成员别名。与
中的问题相同#include <array>
int main()
{
using arr_t = std::array<int,42>&;
using elem_broken = arr_t::value_type; // error
using elem_t = std::decay_t<arr_t>::value_type; // ok
}
您对 SFINAE 使用
std::decay_t
,但在查询成员别名时却错过了使用它。
template <typename T>
std::enable_if_t<is_array<std::decay_t<T>>::value>
do_something_prob(T&& arr, typename std::decay_t<T>::value_type mul);