Consider a BasicCharp class with two constructors:
template <class CharType>
class BasicCharp {
public:
using value_type = CharType;
using pointer = value_type*;
public:
//1
template<size_t SIZE>
constexpr BasicCharp(value_type (&str)[SIZE]) noexcept
: m_Length(SIZE)
, m_String(str) {}
//2
constexpr BasicCharp(pointer string) noexcept
: m_Length(countElems(string))
, m_String(string) {}
private:
size_t m_Length;
pointer m_String;
};
Constructing:
BasicCharp<const char> str = "test";
This calls constructor 2, however if there is no constructor 2, this does call constructor 1.
How to keep constructor 2, but enforce using constructor 1 if possible?
A c 17 solution is preferred, but any standart is welcome.
The goal is to deduce string literal's size at compile time, but if a pointer is passed, size should be calculated by the constructor.
CodePudding user response:
Your overloads are ambiguous; a decayed array pointer is no better or worse candidate than a non-decayed one. It only compiles because non-template overloads are a better match than template ones.
What you can do is make the pointer overload a worse overload candidate, e.g. by introducing a user-defined conversion sequence.
struct ptr { pointer p; ptr(pointer p) : p(p) {} };
constexpr BasicCharp(ptr string) noexcept
: m_Length(countElems(string.p))
, m_String(string.p) {}
CodePudding user response:
Not exactly the same, but you might tag dispatch, something like:
template <typename > struct Tag{};
template <class CharType>
class BasicCharp {
// ...
public:
template<typename T>
constexpr BasicCharp(const T& str) noexcept : BasicCharp(str, Tag<T>{})
{
// Or alternatively, use if constexpr here
}
private:
template<std::size_t SIZE>
constexpr BasicCharp(const value_type (&str)[SIZE],
Tag<value_type[SIZE]>) noexcept
: m_Length(SIZE)
, m_String(str) {}
constexpr BasicCharp(const value_type*string, Tag<const value_type*>) noexcept
: m_Length(countElems(string))
, m_String(string) {}
};
CodePudding user response:
You can assign the result to constexpr variable, but it is not 100% garanted that this will be done compile time, also you can use consteval, in this case if variable isn't assigned compile time you will get error(consteval works from c 20)