Restrict passed parameter to a string literal

前端 未结 6 1194
没有蜡笔的小新
没有蜡笔的小新 2020-12-03 23:20

I have a class to wrap string literals and calculate the size at compile time.

The constructor looks like this:

template< std::size_t N >
Liter         


        
6条回答
  •  暗喜
    暗喜 (楼主)
    2020-12-03 23:42

    I once came up with a C++98 version that uses an approach similar to the one proposed by @k.st. I'll add this for the sake of completeness to address some of the critique wrt the C++98 macro. This version tries to enforce good behavior by preventing direct construction via a private ctor and moving the only accessible factory function into a detail namespace which in turn is used by the "offical" creation macro. Not exactly pretty, but a bit more fool proof. This way, users have to at least explicitly use functionality that is obviously marked as internal if they want to misbehave. As always, there is no way to protect against intentional malignity.

    class StringLiteral
    {
    private:
        // Direct usage is forbidden. Use STRING_LITERAL() macro instead.
        friend StringLiteral detail::CreateStringLiteral(const char* str);
        explicit StringLiteral(const char* str) : m_string(str)
        {}
    
    public:
        operator const char*() const { return m_string; }
    
    private:
        const char* m_string;
    };
    
    namespace detail {
    
    StringLiteral CreateStringLiteral(const char* str)
    {
        return StringLiteral(str);
    }
    
    } // namespace detail
    
    #define STRING_LITERAL_INTERNAL(a, b) detail::CreateStringLiteral(a##b)
    
    /**
    *   \brief The only way to create a \ref StringLiteral "StringLiteral" object.
    *   This will not compile if used with anything that is not a string literal.
    */
    #define STRING_LITERAL(str) STRING_LITERAL_INTERNAL(str, "")
    

提交回复
热议问题