@@ -59,6 +59,7 @@ inline void assign(Tuple1&& x, Tuple2&& y, const char* name);
59
59
template <
60
60
typename T, typename U,
61
61
require_t <std::is_assignable<std::decay_t <T>&, std::decay_t <U>>>* = nullptr ,
62
+ require_all_not_std_vector_t <T, U>* = nullptr ,
62
63
math::require_all_not_tuple_t <T, U>* = nullptr >
63
64
inline void assign (T&& x, U&& y, const char * name) {
64
65
internal::assign_impl (x, std::forward<U>(y), name);
@@ -776,15 +777,25 @@ inline void assign(Mat1&& x, Mat2&& y, const char* name, const Idx& row_idx,
776
777
* @param[in] y rvalue variable
777
778
* @param[in] name name of lvalue variable
778
779
*/
779
- template <typename T, typename U, require_all_std_vector_t <T, U>* = nullptr ,
780
- require_not_t <
781
- std::is_assignable<std::decay_t <T>&, std::decay_t <U>>>* = nullptr >
780
+ template <typename T, typename U, require_all_std_vector_t <T, U>* = nullptr >
782
781
inline void assign (T&& x, U&& y, const char * name) {
783
782
if (unlikely (x.size () != 0 )) {
784
783
stan::math::check_size_match (" assign array size" , name, x.size (),
785
784
" right hand side" , y.size ());
786
785
}
787
- if (std::is_rvalue_reference<U&&>::value) {
786
+
787
+ if constexpr (std::is_assignable_v<std::decay_t <T>&, std::decay_t <U>>) {
788
+ if (is_stan_scalar_v<value_type_t <T>> || x.size () == 0 ) {
789
+ x = std::forward<U>(y);
790
+ return ;
791
+ }
792
+ }
793
+
794
+ // If we've made it this far, we need x to have elements to assign to,
795
+ // and we know this is either a no-op or x has size 0, which we treat as
796
+ // a wildcard that can take any size.
797
+ x.resize (y.size ());
798
+ if constexpr (std::is_rvalue_reference_v<U&&>) {
788
799
for (size_t i = 0 ; i < y.size (); ++i) {
789
800
assign (x[i], std::move (y[i]), name);
790
801
}
0 commit comments