C++

1755 readers
1 users here now

The center for all discussion and news regarding C++.

Rules

founded 1 year ago
MODERATORS
101
 
 

The talk goes over std::any, std::variant, std::tuple, CRTP and deducing this.

102
 
 

Hello!

I've been working on this language for the past 5 years, ArkScript, which is:

  • as small as I could (language wise, 10 keywords, nothing I deemed too specific/useless)
  • running on a VM, compile once run anywhere, just ship your bytecode
  • can be used as a scripting language on its own, like python (though it's not its strength)
  • easy to embed, made in c++ 17 with simplicity in mind

I'm currently working on the v4 (I screwed up with the semver), redoing the imports syntax, and currently cleaning the code and rewriting all the unit tests using boosr-ext/ut.

I'm open to criticism, suggestions, discussions on how to enhance it, or just questions on that weird project.

103
104
105
 
 

KCP is an algorithmic transport protocol which provides reliability and sequencing for unreliable channels like UDP. By algorithmic it means it doesn't care about sockets, and even clock has to be provided externally.

It uses fast acknowledgements and has basic congestion+flow control, has an overhead of 24 bytes per packet/ack, but survives bad network conditions much better than TCP and doesn't require retransmitting all packets after the lost one, making it viable for realtime games.

Original code is written in C and hasn't been updated for a while so I decided to bring my own spin. Also fixed several bugs in the meantime.

This is my personal project which is currently in active development, but it has passed internal tests in our team and is considered semi-ready for production use. Basic tests for sanity checks are included.

106
107
5
Safer Usage Of C++ (2021) (docs.google.com)
submitted 9 months ago by lysdexic to c/cpp
108
109
110
111
13
submitted 9 months ago by lysdexic to c/cpp
112
10
Learn Modern C++ (learnmoderncpp.com)
submitted 10 months ago by lysdexic to c/cpp
113
 
 

The examples shown below are just toy examples, if you weren't already able to catch on.

In the code snippet below, how should we implement pair_typeid?

class Base1{
    public:
        constexpr virtual ~Base1() noexcept = default;
    protected:
        constexpr Base1() noexcept = default;
        constexpr Base1(const Base1&) noexcept = default;
        constexpr Base1(Base1&&) noexcept = default;

        constexpr Base1& operator=(const Base1&) noexcept = default;
        constexpr Base1& operator=(Base1&&) noexcept = default;
};

class Base2{
    public:
        constexpr virtual ~Base2() noexcept = default;
    protected:
        constexpr Base2() noexcept = default;
        constexpr Base2(const Base2&) noexcept = default;
        constexpr Base2(Base2&&) noexcept = default;

        constexpr Base2& operator=(const Base2&) noexcept = default;
        constexpr Base2& operator=(Base2&&) noexcept = default;
};

class Derived1_1 final: public Base1{/* code */};

class Derived1_2 final: public Base1{/* code */};

class Derived2_1 final: public Base2{/* code */};

class Derived2_2 final: public Base2{/* code */};

/**
 * @brief Gets the `typeid(std::pair<dynamic type of 1st param, dynamic type of 2nd param>)`.
 * 
 * More formally, `pair_typeid(r1, r2) == typeid(std::pair<T1, T2>)`
 * where `T1` is the dynamic type of the referent of `r1`
 * and `T2` is the dynamic type of the referent of `r2`.
 * 
 * @return `const std::type_info&`
 */
constexpr const std::type_info& pair_typeid(const Base1&, const Base2&) noexcept;

If Derived1_1, Derived1_2, Derived2_1, and Derived2_2 were the only classes to use this function, we could use dynamic_cast or typeid, but that's inelegant so we instead use the visitor pattern in the below impl, because it avoids this. Note how we restrict the extent of the double dispatch.

class Base1;

class Base2;

class Derived2_1;

class Derived2_2;

namespace detail{
    template <class T>
    constexpr const std::type_info& visit_pair_typeid(const Base1&, const T&) noexcept;
}

class Base1{
    public:
        constexpr virtual ~Base1() noexcept = default;
    protected:
        constexpr Base1() noexcept = default;
        constexpr Base1(const Base1&) noexcept = default;
        constexpr Base1(Base1&&) noexcept = default;

        constexpr Base1& operator=(const Base1&) noexcept = default;
        constexpr Base1& operator=(Base1&&) noexcept = default;

        constexpr virtual const std::type_info& visit_pair_typeid(const Derived2_1&) const noexcept = 0;
        constexpr virtual const std::type_info& visit_pair_typeid(const Derived2_2&) const noexcept = 0;

        template <class T>
        friend constexpr const std::type_info& detail::visit_pair_typeid(const Base1&, const T&) noexcept;
};

template <class T>
constexpr const std::type_info& detail::visit_pair_typeid(const Base1& star_this, const T& acceptor) noexcept{return star_this.visit_pair_typeid(acceptor);}

/**
 * @brief Gets the `typeid(std::pair<dynamic type of 1st param, dynamic type of 2nd param>)`.
 * 
 * More formally, `pair_typeid(r1, r2) == typeid(std::pair<T1, T2>)`
 * where `T1` is the dynamic type of the referent of `r1`
 * and `T2` is the dynamic type of the referent of `r2`.
 * 
 * @return `const std::type_info&`
 */
constexpr const std::type_info& pair_typeid(const Base1&, const Base2&) noexcept;

class Base2{
    public:
        constexpr virtual ~Base2() noexcept = default;
    protected:
        constexpr Base2() noexcept = default;
        constexpr Base2(const Base2&) noexcept = default;
        constexpr Base2(Base2&&) noexcept = default;

        constexpr Base2& operator=(const Base2&) noexcept = default;
        constexpr Base2& operator=(Base2&&) noexcept = default;

        constexpr virtual const std::type_info& accept_pair_typeid(const Base1&) const noexcept = 0;

        template 
        static constexpr const std::type_info& accept_pair_typeid_impl(const T& star_this, const Base1& visitor) noexcept{return detail::visit_pair_typeid(visitor, star_this);}

        friend constexpr const std::type_info& pair_typeid(const Base1& r1, const Base2& r2) noexcept{return r2.accept_pair_typeid(r1);}
};

class Derived2_1 final: public Base2{
    protected:
        constexpr const std::type_info& accept_pair_typeid(const Base1& visitor) const noexcept final{return accept_pair_typeid_impl(*this, visitor);}
};

class Derived2_2 final: public Base2{
    protected:
        constexpr const std::type_info& accept_pair_typeid(const Base1& visitor) const noexcept final{return accept_pair_typeid_impl(*this, visitor);}
};

class Derived1_1 final: public Base1{
    protected:
        constexpr const std::type_info& visit_pair_typeid(const Derived2_1&) const noexcept final{return typeid(std::pair<Derived1_1, Derived2_1>);}
        constexpr const std::type_info& visit_pair_typeid(const Derived2_2&) const noexcept final{return typeid(std::pair<Derived1_1, Derived2_2>);}
};

class Derived1_2 final: public Base1{
    protected:
        constexpr const std::type_info& visit_pair_typeid(const Derived2_1&) const noexcept final{return typeid(std::pair<Derived1_2, Derived2_1>);}
        constexpr const std::type_info& visit_pair_typeid(const Derived2_2&) const noexcept final{return typeid(std::pair<Derived1_2, Derived2_2>);}
};

A minor benefit of the visitor pattern is that adding more visitors is extremely easy. This allows templatization of the visitor.

class Base1;

class Base2;

class Derived2_1;

class Derived2_2;

namespace detail{
    template <class T>
    constexpr const std::type_info& visit_pair_typeid(const Base1&, const T&) noexcept;
}

class Base1{
    public:
        constexpr virtual ~Base1() noexcept = default;
    protected:
        constexpr Base1() noexcept = default;
        constexpr Base1(const Base1&) noexcept = default;
        constexpr Base1(Base1&&) noexcept = default;

        constexpr Base1& operator=(const Base1&) noexcept = default;
        constexpr Base1& operator=(Base1&&) noexcept = default;

        constexpr virtual const std::type_info& visit_pair_typeid(const Derived2_1&) const noexcept = 0;
        constexpr virtual const std::type_info& visit_pair_typeid(const Derived2_2&) const noexcept = 0;

        template <class T>
        friend constexpr const std::type_info& detail::visit_pair_typeid(const Base1&, const T&) noexcept;
};

template <class T>
constexpr const std::type_info& detail::visit_pair_typeid(const Base1& star_this, const T& acceptor) noexcept{return star_this.visit_pair_typeid(acceptor);}

/**
 * @brief Gets the `typeid(std::pair<dynamic type of 1st param, dynamic type of 2nd param>)`.
 * 
 * More formally, `pair_typeid(r1, r2) == typeid(std::pair<T1, T2>)`
 * where `T1` is the dynamic type of the referent of `r1`
 * and `T2` is the dynamic type of the referent of `r2`.
 * 
 * @return `const std::type_info&`
 */
constexpr const std::type_info& pair_typeid(const Base1&, const Base2&) noexcept;

class Base2{
    public:
        constexpr virtual ~Base2() noexcept = default;
    protected:
        constexpr Base2() noexcept = default;
        constexpr Base2(const Base2&) noexcept = default;
        constexpr Base2(Base2&&) noexcept = default;

        constexpr Base2& operator=(const Base2&) noexcept = default;
        constexpr Base2& operator=(Base2&&) noexcept = default;

        constexpr virtual const std::type_info& accept_pair_typeid(const Base1&) const noexcept = 0;

        template <class T>
        static constexpr const std::type_info& accept_pair_typeid_impl(const T& star_this, const Base1& visitor) noexcept{return detail::visit_pair_typeid(visitor, star_this);}

        friend constexpr const std::type_info& pair_typeid(const Base1& r1, const Base2& r2) noexcept{return r2.accept_pair_typeid(r1);}
};

class Derived2_1 final: public Base2{
    protected:
        constexpr const std::type_info& accept_pair_typeid(const Base1& visitor) const noexcept final{return accept_pair_typeid_impl(*this, visitor);}
};

class Derived2_2 final: public Base2{
    protected:
        constexpr const std::type_info& accept_pair_typeid(const Base1& visitor) const noexcept final{return accept_pair_typeid_impl(*this, visitor);}
};

template <std::size_t N>
class Derived1: public Base1{
    protected:
        constexpr const std::type_info& visit_pair_typeid(const Derived2_1&) const noexcept final{return typeid(std::pair<Derived1, Derived2_1>);}
        constexpr const std::type_info& visit_pair_typeid(const Derived2_2&) const noexcept final{return typeid(std::pair<Derived1, Derived2_2>);}
};

Unfortunately, templatizing the acceptor requires templatizing virtual functions. Workarounds like templatizing base classes don't solve the problem at hand. This problem is a stand-in for a problem where CRTP doesn't work and runtime dispatch is needed, as well as both parameters to the real function being part of an unbounded set of types. What's the real solution to the problem? Which idiom can I use?

114
20
submitted 10 months ago by lysdexic to c/cpp
115
18
C++ Should Be C++ (www.open-std.org)
submitted 10 months ago by lysdexic to c/cpp
116
8
MISRA C++:2023 published (forum.misra.org.uk)
submitted 10 months ago by lysdexic to c/cpp
 
 

MISRA is very pleased to announce the release of the new version of MISRA C++; MISRA C++:2023 Guidelines for the use C++:17 in critical systems

Published in October 2023, this is the latest and current edition of MISRA C++. It is specifically targetting the 2017 language version (C++:17) as defined by ISO/IEC 14882:2017.

117
118
119
120
13
submitted 10 months ago by lysdexic to c/cpp
 
 

Here's the release notes: https://cmake.org/cmake/help/v3.28/release/3.28.html

Perhaps the update that's the most interesting - C++20 named modules support by Ninja:

C++ 20 named modules are now supported by Ninja Generators and Visual Studio Generators for VS 2022 and newer, in combination with the MSVC 14.34 toolset (provided with VS 17.4) and newer, LLVM/Clang 16.0 and newer, and GCC 14 (after the 2023-09-20 daily bump) and newer. See cmake-cxxmodules(7) for details.

121
122
 
 

I was doing the (assimp part of this OpenGL tutorial)[https://learnopengl.com/Model-Loading/Model], but in the function loadMaterialTextures, when GetTexture is called, the function ends in an infinite loop and nothing is displayed, why does this happen?

123
124
125
 
 

He uses C++ and the SFML library throughout the course. He just uploaded the last lecture 3 days ago.

view more: ‹ prev next ›