Zobrazit příspěvky

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.


Příspěvky - Baloun

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
Co třeba takto:
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.

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 &currency) {
    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 &currency) {
    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]