struct ResultDeleter
{
typedef HANDLE pointer;
void operator()(pointer ptr) noexcept
{
ResultFree(ptr);
}
};
template<typename P = std::unique_ptr<std::remove_pointer_t<HANDLE>, ResultDeleter>>
inline P ResultPointer(int val) noexcept
{
return P(Result(val));
}
From what I understand, typename P = ...
takes a default type that can be changed by the user. How can I write this to make it unchangeable? I need that typename for the return type, and I don't want to write it twice. I wrote it this way for RVO.
I tried finding what I need in the doc, but I just can't find the information to make me understand what I could do with it.
As requested by @3CEZVQ
#include <windows.h>
#include <memory>
#include <iostream>
struct Deleter
{
typedef BSTR pointer;
void operator()(const pointer ptr) noexcept
{
SysFreeString(ptr);
}
};
template<typename P = std::unique_ptr<std::remove_pointer_t<BSTR>, Deleter>>
inline P BasicString(const LPCWSTR psz) noexcept
{
return P(SysAllocString(psz));
}
int wmain()
{
const auto ptr{ BasicString(L"Templates are not my cup of tea.") };
std::wcout << ptr.get() << std::endl;
return 0;
}
If the goal is just avoid of defining type aliases and using long type names in the code, then it can be
#include <type_traits>
inline std::unique_ptr<std::remove_pointer_t<BSTR>, Deleter> BasicString(
LPCWSTR psz) noexcept {
return std::invoke_result_t<decltype(BasicString), LPCWSTR>{
SysAllocString(psz)};
}
And a better one
inline auto BasicString(LPCWSTR psz) noexcept {
return std::unique_ptr<std::remove_pointer_t<BSTR>, Deleter>{
SysAllocString(psz)};
}
Calls to the first one compile faster in practice (Efficient C++: The hidden compile-time cost of auto return types.)
As for me, I would make a new smart pointer class
class ScopedBasicString {
public:
ScopedBasicString() = default;
explicit ScopedBasicString(LPCWSTR psz);
ScopedBasicString(const ScopedBasicString&) = delete;
ScopedBasicString& operator=(const ScopedBasicString&) = delete;
ScopedBasicString(ScopedBasicString&&) = default;
ScopedBasicString& operator=(ScopedBasicString&&) = default;
BSTR get() const {
return bstr_;
}
// ...
private:
BSTR bstr_ = nullptr;
};
Or use _bstr_t class.