1

I understand that the question sounds a little confusing but bear with me. As I hope that this example might at the bare minimum give you an idea of what I am asking.

If you have a better name for this question, please don't refrain from informing me about it and I shall change it straight away

So here we go!

Suppose I have a class

template <size_t size_of_allocated_memory_in_bytes> class malloc_ptr

inside of which I have a method

template <typename cast_type, bool should_use_c_cast> cast_type cast();

Here is the entire class;

template <size_t size_of_allocated_memory_in_bytes>
class malloc_ptr
{
private:
    void* ptr;

public:
    malloc_ptr()
        : ptr(malloc(size_of_allocated_memory_in_bytes)) {}

    template <typename cast_type , bool should_use_c_cast>
    cast_type cast();

    ~malloc_ptr() noexcept
        { free(ptr); }
};

I understand that I can implement the function like this [with the help of https://stackoverflow.com/questions/27283261/template-function-in-a-templated-class]

template<size_t size_of_allocated_memory_in_bytes> 
template<class cast_type, bool should_use_c_cast> 
cast_type malloc_ptr<size_of_allocated_memory_in_bytes>::cast()
{
    return reinterpret_cast<cast_type>(ptr);
}

However I only want the function to be implemented when should_use_c_cast == true but I have no clue on how to do that.


I hope that you all could help with this. Moreover, any help would be greatly appreciated. And Thank You in advance!

2 Answers2

3

If you want to have one implementation for true, and one for false, you need C++17's if constexpr, because you can't partially specialise a function template.

template<size_t size> 
template<class cast_type, bool should_use_c_cast> 
cast_type malloc_ptr<size>::cast()
{
    if constexpr (should_use_c_cast) {
        return reinterpret_cast<cast_type>(ptr);
    } else {
        // false case here
    }
}

However, your should_use_c_cast case has undefined behaviour, so I'd suggest you don't even need should_use_c_cast, and instead use placement new. It is also suspicious that you are using malloc, because objects have alignment requirements, so if malloc returns an unaligned pointer, your program will again have undefined behaviour.

template <size_t size, size_t align = size>
class malloc_ptr
{
private:
    void* ptr;

public:
    malloc_ptr()
        : ptr(aligned_alloc(align, size)) {}

    template <typename cast_type>
    cast_type * cast();

    ~malloc_ptr() noexcept
        { free(ptr); }
};

template<size_t size_of_allocated_memory_in_bytes> 
template<class cast_type> 
cast_type * malloc_ptr<size_of_allocated_memory_in_bytes>::cast()
{
    return new (ptr) cast_type;
}
Caleth
  • 52,200
  • 2
  • 44
  • 75
1

One way is to use enable_if as shown below:

template <size_t size_of_allocated_memory_in_bytes>
class malloc_ptr
{
private:

public:
    
    template <typename cast_type , bool should_use_c_cast>
//-------------------vvvvvvvvvvvvvvvvv--------------------->condition here
    std::enable_if_t<should_use_c_cast,cast_type> cast();

};

With C++20 you can use requires:

template <size_t size_of_allocated_memory_in_bytes>
class malloc_ptr
{
private:

public:
    
    template <typename cast_type , bool should_use_c_cast>
    cast_type cast() requires(should_use_c_cast);

};
Jason
  • 36,170
  • 5
  • 26
  • 60