mercredi 6 décembre 2023

How to Extend C++ Type Traits to Support Pointers and References?

I'm working on a type traits class in C++ and need some assistance in extending its functionality to cover pointers and references. Currently, my class provides traits to check if a type is derived from another, if it's a class or struct, and if it's a primitive or integer type. However, it fails when dealing with pointers or references, as it only considers the direct type.

Here is the existing implementation:

template <typename Derived, typename Base>
using is_derived_from = std::is_base_of<Base, Derived>;

template <typename Type>
using is_class = std::is_class<Type>;

template <typename primitiveT>
using is_primitive = std::integral_constant<bool,
    std::is_floating_point<primitiveT>::value ||
    std::is_integral<primitiveT>::value>;

template <typename TypeInt>
using is_integer = std::integral_constant<bool,
    std::is_integral<TypeInt>::value && !std::is_same<TypeInt, bool>::value>;

template <typename Type, typename Expected>
using is_valid_type = std::integral_constant<bool,
    (is_primitive<Type>::value && std::is_same<Type, Expected>::value) ||
    (is_class<Type>::value && is_derived_from<Type, Expected>::value)
>;

I want to modify is_valid_type to also correctly handle pointers and references. For example, if Type is a pointer or reference to a class derived from Expected, or a pointer/reference to a primitive type that matches Expected, it should still be considered valid.

I've considered using std::remove_pointer and std::remove_reference, but I'm unsure how to integrate them effectively without complicating the code too much.

Any suggestions on how to modify is_valid_type or the approach in general to handle pointers and references efficiently and elegantly in C++?

mardi 5 décembre 2023

std::function - function uses ‘auto’ type specifier without trailing return type in C++ 11 [duplicate]

I'm trying to get a C++14 library working with our C++ 11 code base and having trouble with using std::function (of which I know very little).

Minimal code:

#include <functional>
#include <iostream>

class A
{
public:
    A() {}
    ~A() {}
    
    using CallbackFn = std::function<int(int, double)>;
    auto GetCallbackFn() const { return mCallbackFcn.target<int (*)(int, double)>(); }

private:
   CallbackFn mCallbackFcn;

};

int main()
{
    std::cout << "hi there\n";
}

The code compiles without error with C++14 but with C++11 produces an error:

main.cpp:20:5: error: ‘GetCallbackFn’ function uses ‘auto’ type specifier without trailing return type

I've tried replacing auto with CallbackFn and other permutations but all end up with one error or another.

How do I modify the code to compile under C++11?

Thanks

lundi 4 décembre 2023

How to translate a np.array.view() operation to c++ function

How can I perform this operation in c++ : y = y.view(dtype=int64) * (2**-18), where y is a numpy array where each element holds 16 uint8_t values (128-bits in total).

This is my input y :

[0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0],
[0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0],
[209  97 173 255 255 255 255 255 157 210  83   0   0   0   0   0],
[ 99 139 170 255 255 255 255 255   4 214  86   0   0   0   0   0],
[ 46 172 247 255 255 255 255 255 225 125   8   0   0   0   0   0],
[178 109 184 255 255 255 255 255 223 166  72   0   0   0   0   0],
[0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0],
[0 0 4 0 0 0 0 0 0 0 0 0 0 0 0 0]

and here is the expected output:

y_fpga: [[  1.           0.        ]
 [  1.           0.        ]
 [-20.65447617  20.95567703]
 [-21.36388016  21.70899963]
 [ -2.08185577   2.12292862]
 [-17.89287567  18.16296005]
 [  1.           0.        ]
 [  1.           0.        ]]

What are the rules for uniform initialization of a union [duplicate]

If i compile the following code ...

int main() 
{
    union U
    {
        struct { int i, j; } s;
        long long x, y;
        int z;
    };
    U li { 1 };
}

... either x or y becomes initialized with 1 from what I can deduce from the didsassembly. I noticed that when initializing a LARGE_INTERGER with Win32, where the QuadPart becomes initialized, which is very convenient for me.
But what are the rules for static initalization of unions ? Which part of the union is applied with the initialization value if there's no constructor ?
Edit: I've removed the language-lawyer tag someone applied here because I won't judge on that.

C++11 Memory model: the compiler is restricted to don't introduce new data races

Watching a CppCon talk by Michel Wong on 2015 (called C++1/14/17 atomics and memory model... about minute 33:00), he said two sentences that I didn't understand:

No compiler transformation is allowed to introduce a data race (more restrictions on invented writes and possibly fewer speculative stores and potentially loads)

What kind of "invented writes" and "speculative stores and loads" did compiler do, which of those were "common" before the C++11 memory model but now are forbidden? Were those important optimizations that are now lost? Or they had a tiny impact anyway?

There are atomic memory operations that don't cause races (or they race but are well-defined)

What does he mean here by "there are"? In the hardware or does he is refering to some C++ built-in operations? Which memory operations can "cause races but are well-defined"?

dimanche 3 décembre 2023

Generic Container Template Supporting Various Data Structures in C++ 14

Hi StackOverflow community,

I am working on creating a generic container class template in C++ that can support various data structures like std::vector std::map , etc. My goal is to make this container flexible enough to handle different types of data structures and provide a uniform interface for operations like Add and Remove.

Here is the code snippet that I have so far:

With this implementation I can create a general interface for my container, but I'm specifically looking to improve the functionality of std::map. I want to be able to add and remove items for maps in two ways:

`#include <iostream>
#include <vector>
#include <map>

template <typename T>
class IContainer
{
public:
    virtual void Add(const T& item) = 0;     // Adds item
    virtual void Remove(const T& item) = 0;  // Remove the item if it exists in the container
    virtual ~IContainer() = default;
};

template <typename T, typename ContainerType>
class Container : public IContainer<T>
{
public:
    void Add(const T& item) override
    {
        container.Add(item);
    }

    void Remove(const T& item) override
    {
        container.Remove(item);
    }

private:
    ContainerType container;
};

template <typename T>
class VectorContainer
{
public:
    void Add(const T& item)
    {
        vect.push_back(item);
    }

    void Remove(const T& item)
    {
        // Assuming T has a valid equality comparison
        auto it = std::remove(vect.begin(), vect.end(), item);
        vect.erase(it, vect.end());
    }

private:
    std::vector<T> vect;
};

template <typename Key, typename Value>
class MapContainer
{
public:
    void Add(const std::pair<const Key, Value>& keyValue)
    {
        container.insert(keyValue);
    }

    void Add(const Key& key, const Value& value)
    {
        container[key] = value;
    }

    void Remove(const std::pair<const Key, Value>& keyValue)
    {
        container.erase(keyValue.first);
    }

private:
    std::map<Key, Value> container;
};

int main()
{
    Container<int, VectorContainer<int>> myCont;
    myCont.Add(1); // myCont has a generic interface thanks to IContainer

    Container<std::pair<const std::string, int>, MapContainer<std::string, int>> mapCont;
    mapCont.Add({"key1", 42});
    mapCont.Add("key2", 88); // Using the new Add function (not working)

    return 0;
}
`

Using std::pair as a single parameter. Using separate key and value parameters. I implemented the Add method for both cases, but the container does not support separate keys and key values, so I'm not sure if this is the most efficient or correct way to achieve this flexibility. I'm also looking for suggestions to make this template more compatible with other container types.

Can someone provide insight or improvements on how to do the following:

Efficiently support both append methods for std::map. Generalize this approach to effectively cover other container types. Any advice or code sample would be greatly appreciated!

Thank you!

samedi 2 décembre 2023

Lack of LLVM support

LLVM is such a powerful tool, it is very well established and has a large community. As an undergraduate student I had project and needed to use the LLVM API. Words cannot describe how traumatised I am. I understand that LLVM is huge and very well documented, but I found it extremely hard to do even the most basic tasks. I just wanted to see if others face this problem or is it just me? Are people using LLVM already senior developers with years of experience or do companies such as Apple, Google, etc. gatekeep their resources? I am just very interested in the aspect of low-level compiler design in the future, so any advice would be very much appreciated!

Not only did I spent hours on the official website trying to find my way though, which was like navigating an online labyrinth from the 1990s, I also spent a large amount of time trying to find other web resources/forums, that were mostly useless!