Estou olhando cppreference mas não vejo nenhuma informação sobre a ordem do loop executado.
Minha pergunta : ao ligar, std::ranges::any_of
tenho data.begin(), data.end()
certeza de que vai de begin()
para end()
em ordem e para uma vez true
?
Estou olhando cppreference mas não vejo nenhuma informação sobre a ordem do loop executado.
Minha pergunta : ao ligar, std::ranges::any_of
tenho data.begin(), data.end()
certeza de que vai de begin()
para end()
em ordem e para uma vez true
?
Olhando a documentação , não entendo por que std::make_format_args()
pega uma referência e não uma referência const?
Meu objetivo é implementar algo como:
#include <format>
template <class... Args>
inline static std::string format(const std::string_view field, Args&&... args)
{
return std::vformat(field, std::make_format_args(std::forward<Args>(args)...));
}
E poder passar const std::string&
como entrada args
, mas parece que std::make_format_args()
espera uma referência não const.
Eu recebo um erro:
A non-const reference may only be bound to an lvalue C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.40.33807\include\format(3713): note: see declaration of 'std::make_format_args'
note: while trying to match the argument list '(_Ty, const std::string, _Ty, _Ty)'
ATUALIZAR
Posso reproduzir o erro aqui: https://godbolt.org/z/nj763o48r (localmente recebo exatamente o mesmo erro acima)
Ao declarar static thread_local
uma variável, cada thread possui uma cópia dessa variável. Imagine que um thread gira outro thread. Essa variável ainda será uma cópia no thread aninhado?
Estou usando perform_mapping
from link como aqui link , mas recebo um erro de compilação.
#include <string>
#include <tuple>
#include <utility>
#include <string>
#include <type_traits>
namespace details
{
template <typename Tuple, typename Mapping>
struct return_type;
template <template <typename ...> typename Tuple, typename ... Types, typename Mapping>
struct return_type<Tuple<Types...>, Mapping>
{
//I changed the below line from what is in the link
using type = Tuple<decltype(std::invoke_result<Mapping, Types>())...>;
};
template <template <typename, std::size_t> typename Array, typename T, std::size_t Size, typename Mapping>
struct return_type<Array<T, Size>, Mapping>
{
using type = Array<std::invoke_result_t<Mapping, T>, Size>;
};
template <typename Tuple, typename Mapping>
using return_type_t = typename return_type<Tuple, Mapping>::type;
template <typename Tuple, typename Mapping, std::size_t ... Indices>
return_type_t<std::decay_t<Tuple>, std::decay_t<Mapping>> perform_mapping(Tuple&& tup, Mapping&& mapping, std::index_sequence<Indices...>)
{
return {mapping(std::get<Indices>(std::forward<Tuple>(tup)))...};
}
}
template <typename Tuple, typename Mapping,
std::size_t Size = std::tuple_size<std::decay_t<Tuple>>::value>
auto perform_mapping(Tuple&& tup, Mapping&& mapping)
{
return details::perform_mapping(std::forward<Tuple>(tup), std::forward<Mapping>(mapping), std::make_index_sequence<Size>{});
}
struct A
{
A(double z) : x(z){};
double x;
using Type = double;
};
struct B
{
B(std::string s) : x(std::move(s)) {}
std::string x;
using Type = std::string;
};
struct C
{
C() : m_tuple({A(1.0), B("A")})
{
}
template<class T>
typename T::Type f(T& z)
{
return z.x;
}
std::tuple<A::Type, B::Type> get()
{
return perform_mapping(m_tuple, [this](auto& z) { return this->f(z); });
}
std::tuple<A, B> m_tuple;
};
int main()
{
C c;
auto t = c.get();
};
Minha dúvida é: Posso implementar perform_mapping
de forma que o código acima funcione?
Existe uma maneira de inicializar uma estrutura filho usando chaves, incluindo variáveis de membro da estrutura base. Estou tentando o abaixo, mas não compila (usando VS e C++ 20). Não quero criar um construtor e gostaria de usar uma construção de uma linha .
struct Base
{
int n;
};
struct Derived : Base
{
std::string s;
};
static const Derived d1{ .s = "Hi", { .n = 1 } }; //fails to compile
static const Derived d2{ 1, { "Hi" } }; //fails to compile
static const Derived d3{ 1, "Hi" }; //fails to compile
static const Derived d4(1, "Hi"); //fails to compile
EDIT : d4, d3
na verdade, compile bem.
O cliente mantém um ponteiro compartilhado para um valor, digamos double
, e um servidor atualiza esse valor em outro thread desanexado, mantendo um weak_pointer
, o servidor verifica se weak_pointer
expirou e, se não estiver, é excluído de um vetor seguro. Suspeito que isso não funcionaria, pois poderia shared_ptr
ser destruído do lado do cliente entre minha leitura expired()
(que considero thread-safe, pois imagino que se refere ao contador atômico de shared_ptr
) e minha atualização do valor. Existe uma maneira de fazer com que a verificação expired()
e uma lambda
função atualizem o valor antes que ele seja destruído, por favor? Quero dizer:
struct server
{
public:
static void subscribe(const std::shared_ptr<double>& d)
{
m_values.safe_push_back(d); //safely pushes back in the vector
}
void update()
{
auto updater = [](std::weak_ptr<double>& wd)
{
if(wd.expired()) wd = nullptr;
else *wd += 2.0; //This is not thread safe I guess?
};
m_values.safe_remove_all(nullptr);
m_values.safe_visit(updater);
};
private:
static safe_vector<std::weak_ptr<double>> m_values;
}
struct client
{
void subcribe_sleep_print(const double random_seconds)
{
std::shared_ptr<double> d = std::make_shared<double>(0.0); //for the sake of the example assume we create subscribe before sleep
server::subscribe(d);
sleep_for_seconds(random_seconds); //sleeps for some random time in seconds.
std::cout << *d << std::endl;
}
}
Imagine server::update
e client::subcribe_sleep_print
esteja rodando em threads diferentes. Isso não é seguro, pois shared_ptr
pode ser destruído enquanto o servidor está gravando? Existe uma maneira de fazer isso sem atômicos ou mutexes definidos pelo usuário (eu)? Não me importo se for usado em segundo plano, desde que eu mesmo não os adicione (atômico/mutex), pois sei que o ponteiro compartilhado já usa um contador atômico.
EDIT : Não estou usando double no meu programa, estou usando um objeto thread-safe :) Portanto, a operação += pode ser assumida como thread-safe. Desculpe.
Contexto : Eu tenho uma fila que suporta leitura única/gravação única de dois threads diferentes (/ou não), para impor esse comportamento, ou seja, leitor único/gravador único por vez, preciso limitar o número de threads proprietários a fila por vez para 2 (o escritor já possui a fila), eu estava pensando em criar um shared_ptr para a fila com uma contagem máxima de referências conhecida em tempo de compilação definida como 2. Portanto, minha pergunta é a seguinte.
Pergunta : Existe uma maneira de implementar um ponteiro compartilhado (talvez usando unique_pointer
's) com uma contagem máxima de referências conhecida em tempo de compilação? Meu caso é, max_ref_count = 2
ou seja, exceder o limite de contagem de referências = 2 deve ser um erro em tempo de compilação.
const auto p = std::make_shared<2, double>(2159); //works fine
const auto q = p; // works fine
const auto err1 = p; // does not compile
const auto err2 = q; // does not compile
Gostaria de construir um tipo que seja uma tupla da mesma classe com diferentes tipos de argumentos de modelo. Quero dizer:
Imagine que temos uma aula
template<class Arg>
class A
{
//.... details
}
Quero definir algo como:
template<class... Args>
struct construct_tuple
{
//assume I can access Args[...]
using type = std::tuple<A<Args[0]>, A<Args[1]>, ..., A<Args[n]>>;
}
Poderia ajudar por favor?
Acredito que pode haver uma solução iterando os argumentos variados e usando a conexão entre tipos de tuplas ou talvez usando algum outro TMP, por exemplo, std::enable_if
ou std::conditional_t
.