c++ 在编译时禁用字段定义

ukqbszuj  于 2023-03-25  发布在  其他
关注(0)|答案(3)|浏览(123)

我想创建一个有/没有线程安全的池。我不想定义一个互斥字段,如果池不是线程安全的,所以我使用了std::conditional,但是因为它没有完全按照我的要求做,并且创建了两个“type”选项,我选择了“int 8(char)”作为被动互斥类型。(相反,我希望整个定义都消失)

template<typename T, bool threadSafe = true>
class Pool
{
private:
    //Mutex mutex; this is the field i want it to be DISAPPEARED, i modified it as below
    std::conditional<threadSafe, Mutex, int8>::type mutex;
protected:
    static constexpr item_type_size_datatype TypeSizeX = sizeof(T) + sizeof(size_t);
public:
    Pool(size_t clusterItemCount) : ClusterItemCount(clusterItemCount),
        ClusterByteSize(clusterItemCount* TypeSizeX)
    {
#ifdef CriticalSection
        if constexpr (threadSafe)
            InitializeCriticalSection(&mutex);
#endif
    }
    ~Pool()
    {
        Clear();

#ifdef CriticalSection
        if constexpr (threadSafe)
            DeleteCriticalSection(&mutex);
#endif
    }

    T* Occupy(bool& outFirstTime)
    {
        if constexpr (threadSafe)
        {
            MutexLock(mutex);
        }

        //do the occupation

        if constexpr (threadSafe)
        {
            MutexUnlock(mutex);
        }

        return result;
    }
};

正如您所看到的,在方法内部,我使用了“constexpr if”,它的工作原理很有魅力,因为它禁用了整个代码块。

**主要问题:**是否有更好的方法来禁用整个定义,如“Mutex mutex;“std::conditional”以外的“
**附加问题:**我收到“int 8 mutex”的“uninitialized variable”警告,我必须使用“0”进行初始化..如何在编译时使用“std::conditional”方式进行初始化。

k7fdbhmy

k7fdbhmy1#

这可以通过模板专门化来实现,例如:

template<bool threadSafe>
class PoolBase;

template<>
class PoolBase<false>
{// empty
};

template<>
class PoolBase<true>
{
   protected: Mutex m_mutex;
};

template<typename T, bool threadSafe = true>
class Pool: private PoolBase<threadSafe>
{
...
ujv3wf0j

ujv3wf0j2#

正如另一个答案所说,你可以使用模板专门化来实现这一点,因为不幸的是,不可能使用std::enable_if来声明成员。
为了使它不需要专门化整个类,从而重复定义和声明,您可以创建一个模板专用的容器结构体,这取决于您是否希望包含变量,然后使用此模板结构体作为成员:

template <bool include_the_thing = true>
struct inner {
    int thing{};
};
template<>
struct inner<false> {};

template <bool include_the_thing>
struct outer {
    inner<include_the_thing> maybe;
};

#include <cassert>

int main() {
    outer<true> has_thing;
    assert(has_thing.maybe.thing == 0);
    outer<false> doesnt_have_thing;
    // assert(doesnt_have_thing.maybe.thing == 0); // compiler error --maybe.thing doesn't exist
}
jgwigjjp

jgwigjjp3#

另一种方法是将Pool作为基类,将线程安全的PoolSafe作为派生类,并进行必要的专门化。

template<typename T>
class Pool
{
protected:
    static constexpr item_type_size_datatype TypeSizeX = sizeof(T) + sizeof(size_t);
public:
    Pool(size_t clusterItemCount) : ClusterItemCount(clusterItemCount),
        ClusterByteSize(clusterItemCount* TypeSizeX)
    {
    }
    virtual ~Pool()
    {
        Clear();
    }
    virtual T* Occupy(bool& outFirstTime)
    {
        //do the occupation
        return result;
    }
};

template<typename T>
class PoolSafe: public Pool<T>
{
private:
    Mutex mutex;
public:
    PoolSafe(size_t clusterItemCount) : Pool<T>(clusterItemCount)
    {
        InitializeCriticalSection(&mutex);
    }
    virtual ~PoolSafe()
    {
        DeleteCriticalSection(&mutex);
    }
    virtual T* Occupy(bool& outFirstTime)
    {
        MutexLock(mutex);
        auto result = Pool<T>::Occupy(outFirstTime);
        MutexUnlock(mutex);
        return result;
    }
};

相关问题