jeudi 22 décembre 2016

How to avoid decay with template parameter deduction

Simplified:

// CHAR_TYPE == char, wchar_t, ...
template <typename CHAR_TYPE, unsigned CHAR_COUNT>
void Foo(CHAR_TYPE const (&value)[CHAR_COUNT])
{
    TRACE("const ref array");
    // perform a bit of logic and forward...
}

template <typename CHAR_TYPE>
void Foo(CHAR_TYPE const* value) noexcept
{
    TRACE("const ptr");
    // perform a bit of logic and forward...
}

// [ several other overloads ]

Callsite:

char const* ptr = ...
wchar_t const* wptr = ...

Foo(ptr);     // <-- good "const ptr"
Foo(wptr);    // <-- good "const ptr"

constexpr char const buffer[] { "blah blah blah" };
constexpr wchar_t const wbuffer[] { L"blah blah blah" };

Foo(buffer);  // <-- ambiguous
Foo(wbuffer); // <-- ambiguous

Of course, I could remove the const ref array overload. However the above calls are over-simplified, and I would like to handle these types differently. I have tried to conditionally enable the correct overload, but I have not been able to determine the necessary condition.

template <typename CHAR_TYPE, unsigned COUNT>
typename std::enable_if</* std::is_?? */, void>::type
    Foo(CHAR_TYPE const (&value)[COUNT])
{
    TRACE("by ref array");
    // perform a bit of logic and forward...
}

template <typename CHAR_TYPE>
typename std::enable_if</* std::is_?? */, void>::type
    Foo(CHAR_TYPE const* value) noexcept
{
    TRACE("ptr");
    // perform a bit of logic and forward...
}

What is the best way to disambiguate these overloads?
(I would prefer not to use an array wrapper)

Aucun commentaire:

Enregistrer un commentaire