1
Tato sekce Vám umožňuje zobrazit všechny příspěvky tohoto uživatele. Prosím uvědomte si, že můžete vidět příspěvky pouze z oblastí Vám přístupných.
Stran: [1]
2
Vývoj / Re:Conditional conformance v OOP
« kdy: 20. 02. 2021, 09:01:29 »
Jestli tomu dobře rozumím, tak to je jako koncepty v C++20. Což je v podstatě jen syntaxe pro SFINAE, který se v C++ používá od doby zavedení šablon.
3
Vývoj / Re:C++ downcast this v předkovi na potomka
« kdy: 16. 02. 2021, 09:17:18 »
Ještě mě napadlo tam přidat CRTP prostředníka, aby to nemusel člověk všude psát.
Kód: [Vybrat]
#include <string>
#include <typeinfo>
#include <iostream>
class Base {
protected:
Base(const std::type_info& derivedType) {
std::cout << "derived: " << derivedType.name() << std::endl;
}
};
template<typename Derived>
class BaseCrtp : public Base {
protected:
BaseCrtp() : Base(typeid(Derived)) {}
};
class Derived : public BaseCrtp<Derived> {
public:
Derived() {}
};
int main() {
Derived{};
return 0;
}
4
Vývoj / Re:C++ downcast this v předkovi na potomka
« kdy: 15. 02. 2021, 16:29:23 »
Virtuální funkci z konstruktoru volat nejde. Potomek v tu dobu ani neexistuje. CRTP zase způsobí, že není jeden předek, ale jen šablona. Proč si teda nepředat potřebné parametry do konstruktoru, který bude protected? Například takto.
Kód: [Vybrat]
#include <string>
#include <typeinfo>
#include <iostream>
class Base {
protected:
Base(const std::type_info& derivedType) {
std::cout << "derived: " << derivedType.name() << std::endl;
}
};
class Derived : public Base {
public:
Derived() : Base(typeid(Derived)) {}
};
int main() {
Derived{};
return 0;
}
5
Vývoj / Re:C++ - template a constexpr pre dvojicu trieda - funkcia
« kdy: 12. 01. 2021, 16:23:35 »
Co třeba takto:
Variant se dá použít pro uložení tříd bez společného předka.
Kód: [Vybrat]
#include <memory>
#include <string>
#include <variant>
struct A{};
struct B{};
struct C{};
template<typename T>
struct Tag{};
A makeGraph(const std::string& in, Tag<A>) {
return A{};
}
B makeGraph(const std::string& in, Tag<B>) {
return B{};
}
C makeGraph(const std::string& in, Tag<C>) {
return C{};
}
template<typename T>
std::variant<A, B, C> makeGraph(const std::string& in) {
return makeGraph(in, Tag<T>{});
}
int main() {
auto graph = makeGraph<A>({});
return 0;
};
Místo různých názvů vytvořujících funkcí, a následného použití constexpr if, stačí odlišit vytvořující funkce pomocí parametru.Variant se dá použít pro uložení tříd bez společného předka.
6
Vývoj / Re:C++ vyfiltrovanie položiek iterátoru a vrátenie ďalšieho iterátoru
« kdy: 12. 01. 2021, 15:58:43 »7
Vývoj / Re:Jake používáte prostředí pro vývoj (C++)_
« kdy: 29. 10. 2020, 08:19:48 »
Qt Creator, Visual Studio Code.
8
Vývoj / Re:Discriminated unions v C++
« kdy: 26. 10. 2020, 13:29:04 »
Pro pořádek dodám i variantu s typy None a AnotherCurrency
Kód: [Vybrat]
#include <variant>
#include <string>
#include <stdexcept>
#include <cassert>
#include <iostream>
enum class CurrencyTag {
Eur,
Usd,
Btc
};
template<CurrencyTag Tag>
struct CurrencyType {
double value = 0;
};
struct None {};
struct AnotherCurrency {
std::string name;
double value = 0;
};
template<CurrencyTag... Tags>
using CurrencyVariant = std::variant<None, AnotherCurrency, CurrencyType<Tags>...>;
using Currency = CurrencyVariant<CurrencyTag::Eur, CurrencyTag::Usd, CurrencyTag::Btc>;
constexpr double EUR_TO_USD = 1.1;
constexpr double BTC_TO_USD = 12000.;
struct ToUsd {
constexpr double operator()(CurrencyType<CurrencyTag::Eur> currency) const {
return currency.value * EUR_TO_USD;
}
constexpr double operator()(CurrencyType<CurrencyTag::Usd> currency) const {
return currency.value;
}
constexpr double operator()(CurrencyType<CurrencyTag::Btc> currency) const {
return currency.value * BTC_TO_USD;
}
template<typename T>
constexpr double operator()(T&& t) const {
throw std::runtime_error("Unsupported currency");
}
};
constexpr double toUsd(const Currency ¤cy) {
return std::visit(ToUsd{}, currency);
}
int main() {
assert(toUsd(CurrencyType<CurrencyTag::Btc>{1.}) == BTC_TO_USD);
try {
toUsd(None{});
} catch (const std::exception& ex) {
std::cerr << ex.what() << std::endl;
}
return 0;
}
9
Vývoj / Re:Discriminated unions v C++
« kdy: 23. 10. 2020, 09:27:51 »
Myslím, že se tu trochu zaměňuje variant/union a pattern matching. Pattern matching v C++ skutečně není. Otagovat si nějaká data ale není problém.
Kód: [Vybrat]
#include <variant>
enum class CurrencyTag {
Eur,
Usd,
Btc
};
template<CurrencyTag Tag>
struct CurrencyType {
double value;
};
template<CurrencyTag... Tags>
using CurrencyVariant = std::variant<CurrencyType<Tags>...>;
using Currency = CurrencyVariant<CurrencyTag::Eur, CurrencyTag::Usd, CurrencyTag::Btc>;
constexpr double EUR_TO_USD = 1/1.1;
constexpr double BTC_TO_USD = 12000.;
constexpr double toUsd(const Currency ¤cy) {
struct ToUsd {
constexpr double operator()(const CurrencyType<CurrencyTag::Eur>& currency) const {
return currency.value * EUR_TO_USD;
}
constexpr double operator()(const CurrencyType<CurrencyTag::Usd>& currency) const {
return currency.value;
}
constexpr double operator()(const CurrencyType<CurrencyTag::Btc>& currency) const {
return currency.value * BTC_TO_USD;
}
};
return std::visit(ToUsd{}, currency);
}
int main() {
static_assert(toUsd(CurrencyType<CurrencyTag::Btc>{1.}) == BTC_TO_USD);
return 0;
}
10
Vývoj / Re:C++ funkcionálny typ
« kdy: 10. 09. 2020, 15:16:42 »
A co třeba takto:
Kód: [Vybrat]
#include <vector>
#include <type_traits>
#include <cassert>
template<typename T, typename R = T>
constexpr auto mul_fun(T multiplier) {
return [multiplier](auto a) -> R {
return a * multiplier;
};
};
template<typename T, typename F>
constexpr auto map(F&& f, const std::vector<T>& v) {
std::vector<std::invoke_result_t<std::remove_cvref_t<F>, T>> ret;
ret.reserve(v.size());
std::transform(std::begin(v), std::end(v), std::back_inserter(ret), std::forward<F>(f));
return ret;
}
int main() {
constexpr auto f = mul_fun(5);
static_assert(f(3) == 15);
std::vector v1{1, 2, 3};
auto v2 = map(f, v1);
assert((v2 == std::vector{5, 10, 15}));
auto v3 = map(mul_fun<double>(2), v2);
assert((v3 == std::vector{10., 20., 30.}));
return 0;
}
Stran: [1]