What is the exact difference of universal reference and rvalue reference?
The code below should except both rvalue reference and lvalue reference as argument. And apparently the first function for_each
takes both successfully. However, when it calls the internal function min_iterable_length, it does not work as expected. It seems that the internal function is expecting only a rvalue reference not lvalue reference.
What is the difference? Apparently the first function for_each did take lvalue reference as legal argument. And I used std::forward to pass it exactly to the second function. And why is the second function only accept rvalue reference?
#include <array>
#include <vector>
#include <utility>
template <typename A, size_t N>
size_t min_iterable_length(A(&&)[N])
{
return N;
}
template <typename A, size_t N>
size_t min_iterable_length(std::array<A, N> &&)
{
return N;
}
template <typename A>
size_t min_iterable_length(std::vector<A> &&vector)
{
return vector.size();
}
template <typename A, size_t N, typename... Args>
size_t min_iterable_length(A (&&head)[N], Args &&...tail)
{
size_t n_t = min_iterable_length(std::forward<Args>(tail)...);
return N < n_t ? N : n_t;
}
template <typename A, size_t N, typename... Args>
size_t min_iterable_length(std::array<A, N> &&head, Args &&...tail)
{
size_t n_t = min_iterable_length(std::forward<Args>(tail)...);
return N < n_t ? N : n_t;
}
template <typename A, typename... Args>
size_t min_iterable_length(std::vector<A> &&head, Args &&...tail)
{
size_t n_h = head.size();
size_t n_t = min_iterable_length(std::forward<Args>(tail)...);
return n_h < n_t ? n_h : n_t;
}
template <typename F, typename... Args>
void for_each(F f, Args &&...args)
{
size_t length = min_iterable_length(std::forward<Args>(args)...);
for (int i = 0; i < length; ++i)
{
f(args[i]...);
}
return;
}
int c_array_3[3] = {1, 2, 3};
int res_1 = 0;
auto add_1 = [&](int x)
{
res_1 += x;
};
for_each(add_1, c_array_3);
[build] /Users/username/Documents/dev/arduino/libraries/efp/test/prelude_test.cpp:32:5: note: in instantiation of function template specialization 'for_each<(lambda at /Users/username/Documents/dev/arduino/libraries/efp/test/prelude_test.cpp:27:18), std::array<double, 3> &>' requested here
[build] for_each(add_2, std_array_3);
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:22:8: note: candidate function [with A = double, N = 3] not viable: expects an rvalue for 1st argument
[build] size_t min_iterable_length(std::array<A, N> &&)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:41:8: note: candidate function [with A = double, N = 3, Args = <>] not viable: expects an rvalue for 1st argument
[build] size_t min_iterable_length(std::array<A, N> &&head, Args &&...tail)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:16:8: note: candidate template ignored: could not match 'A[N]' against 'std::array<double, 3>'
[build] size_t min_iterable_length(A(&)[N])
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:28:8: note: candidate template ignored: could not match 'vector' against 'array'
[build] size_t min_iterable_length(std::vector<A> &&vector)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:34:8: note: candidate template ignored: could not match 'A[N]' against 'std::array<double, 3>'
[build] size_t min_iterable_length(A (&head)[N], Args &&...tail)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:48:8: note: candidate template ignored: could not match 'vector' against 'array'
[build] size_t min_iterable_length(std::vector<A> &&head, Args &&...tail)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:58:21: error: no matching function for call to 'min_iterable_length'
[build] size_t length = min_iterable_length(std::forward<Args>(args)...);
[build] ^~~~~~~~~~~~~~~~~~~
[build] /Users/username/Documents/dev/arduino/libraries/efp/test/prelude_test.cpp:41:5: note: in instantiation of function template specialization 'for_each<(lambda at /Users/username/Documents/dev/arduino/libraries/efp/test/prelude_test.cpp:36:18), std::vector<double> &>' requested here
[build] for_each(add_3, std_vector_3);
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:28:8: note: candidate function [with A = double] not viable: expects an rvalue for 1st argument
[build] size_t min_iterable_length(std::vector<A> &&vector)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:48:8: note: candidate function [with A = double, Args = <>] not viable: expects an rvalue for 1st argument
[build] size_t min_iterable_length(std::vector<A> &&head, Args &&...tail)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:16:8: note: candidate template ignored: could not match 'A[N]' against 'std::vector<double>'
[build] size_t min_iterable_length(A(&)[N])
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:22:8: note: candidate template ignored: could not match 'array' against 'vector'
[build] size_t min_iterable_length(std::array<A, N> &&)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:34:8: note: candidate template ignored: could not match 'A[N]' against 'std::vector<double>'
[build] size_t min_iterable_length(A (&head)[N], Args &&...tail)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:41:8: note: candidate template ignored: could not match 'array' against 'vector'
[build] size_t min_iterable_length(std::array<A, N> &&head, Args &&...tail)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:58:21: error: no matching function for call to 'min_iterable_length'
[build] size_t length = min_iterable_length(std::forward<Args>(args)...);
[build] ^~~~~~~~~~~~~~~~~~~
[build] /Users/username/Documents/dev/arduino/libraries/efp/test/prelude_test.cpp:50:5: note: in instantiation of function template specialization 'for_each<(lambda at /Users/username/Documents/dev/arduino/libraries/efp/test/prelude_test.cpp:45:24), std::vector<double> &, int (&)[3]>' requested here
[build] for_each(add_product, std_vector_3, c_array_3);
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:48:8: note: candidate function [with A = double, Args = <int (&)[3]>] not viable: expects an rvalue for 1st argument
[build] size_t min_iterable_length(std::vector<A> &&head, Args &&...tail)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:34:8: note: candidate template ignored: could not match 'A[N]' against 'std::vector<double>'
[build] size_t min_iterable_length(A (&head)[N], Args &&...tail)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:41:8: note: candidate template ignored: could not match 'array' against 'vector'
[build] size_t min_iterable_length(std::array<A, N> &&head, Args &&...tail)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:28:8: note: candidate function template not viable: requires single argument 'vector', but 2 arguments were provided
[build] size_t min_iterable_length(std::vector<A> &&vector)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:22:8: note: candidate function template not viable: requires 1 argument, but 2 were provided
[build] size_t min_iterable_length(std::array<A, N> &&)
[build] ^
[build] /Users/username/Documents/dev/arduino/libraries/efp/./src/prelude.hpp:16:8: note: candidate function template not viable: requires 1 argument, but 2 were provided
[build] size_t min_iterable_length(A(&)[N])