Search code examples
c++c++17overloadingstring-literalscompile-time

How to get string length at compile time if possible?


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.


Solution

  • 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) {}
    };