Просто некоторые дженерики не были выведены. Попробуйте указать их явно
type AllErrorsOr[A] = Validated[List[String], A]
def bothInvalid: AllErrorsOr[(Int, Int)] = {
Semigroupal[AllErrorsOr].product[Int, Int](
Validated.invalid(List("Error 1")),
Validated.invalid(List("Error 2"))
)
}
def bothInvalidTuple: AllErrorsOr[(Int, Int)] = {
Semigroupal.tuple2[AllErrorsOr, Int, Int](
Validated.invalid(List("Error 1")),
Validated.invalid(List("Error 2"))
)
}
def bothValid: AllErrorsOr[(Int, Int)] = {
Semigroupal[AllErrorsOr].product[Int, Int](
Validated.valid(10),
Validated.valid(20)
)
}
def bothValidTuple: AllErrorsOr[(Int, Int)] = {
Semigroupal.tuple2[AllErrorsOr, Int, Int](
Validated.valid(10),
Validated.valid(20)
)
}
Да, но более распространенной идиомой C ++ для этой ситуации является использование ссылки (и, вероятно, ссылки на const) вместо указателя. Таким образом, вместо
void foo( sometype * p ) {
p->func();
}
вы пишете:
void foo( sometype & p ) {
p.func();
}
Это имеет то преимущество, что вам не нужно разыменовывать объект в вызывающей стороне:
void afunc() {
sometype t;
foo( t );
}
, а также дает подсознательный намек читателю, что вы не намереваетесь использовать функцию принять право собственности на объект.
Если вы уверены, что вызов является синхронным, то вполне допустимо отправить адрес выделенного объекта стека в функцию , В случае, если вызов асинхронный (т. Е. Вызванная вами функция передает указатель в другой поток), он определенно создаст проблемы, так как вы можете попытаться получить доступ к адресу памяти из другого потока, даже после уничтожения выделенного стека объекта.
Пока функция приема не предполагает, что она получает право собственности на ресурс (и пытается освободить его) , конечно. Ссылка может быть лучшей идеей, хотя.
Это прекрасно для синхронного вызова функции. Если вызов асинхронный, это может привести к сбою при удалении стекового объекта, когда он выходит из области видимости.
Вы должны быть осторожны, чтобы не хранить этот указатель для дальнейшего использования. Например:
void store(int* param) {
// Store pointer in some global storage for further use
global_storage.add_param(param);
}
void func() {
int test_var = 5;
store(&test_var); // Pass the pointer to the global storage
}
// At this point stack object test_var will be destroyed
// Global storage contains a pointer, that points to some garbage
Это, конечно, верно, но со многими оговорками. Вот главные моменты, о которых следует помнить (некоторые уже упоминались другими, некоторые нет).