Home > Software design >  Template specialization of operator[] within a class with multiple template parameters
Template specialization of operator[] within a class with multiple template parameters

Time:12-28

I'm having trouble specializing 2 methods of a tokenizer class that's declared with 2 template parameters. I've referenced Template specialization of a single method from a templated class but I am still encountering a few errors with my implementation. Some code (specialized functions near EOF):

#pragma once
#include "stdafx.h"
#include <string>
#include <vector>
#include <sstream>
#include <stdexcept>

inline const std::string emptyString = "";
inline const std::wstring emptyWString = L"";

template <class stringT = std::string, class delimiterT = char>
class Tokenizer
{
private:
    std::vector<stringT> tokens;

    bool enableParserThrow;

public:
    Tokenizer(bool throwOnParseError) : enableParserThrow(throwOnParseError)
    {
    }

    Tokenizer(const stringT& tokenizeMe, delimiterT delimiter) : Tokenizer(true)
    {
        TokenizeString(tokenizeMe, delimiter);
    }

    void TokenizeString(const stringT& str, delimiterT delimiter)
    {
        std::stringstream ss;
        ss << str;

        std::string token;
        while (std::getline(ss, token, delimiter))
        {
            tokens.push_back(token);
        }
    }

    template <class T>
    T ParseToken(size_t tokenIndex)
    {
        if (tokenIndex < 0 || tokenIndex >= tokens.size())
        {
            ThrowParserExceptionIfEnabled("Index out of range.");
            return T();
        }

        T temp;
        std::stringstream ss;
        ss << tokens[tokenIndex];
        ss >> temp;

        if (ss.fail())
            ThrowParserExceptionIfEnabled("Parse failure.");

        return temp;
    }

    void Clear()
    {
        tokens.clear();
    }

    const std::vector<stringT>& GetTokens()
    {
        return tokens;
    }

    void ThrowParserExceptionIfEnabled(const char* message)
    {
        if (enableParserThrow)
        {
            throw std::runtime_exception(message);
        }
    }

    // Trying to specialize these functions so I can return a reference to a global empty std::string or std::wstring if tokeIndex is out of range
    template<>
    const std::string& Tokenizer<std::string, delimiterT>::operator[](size_t tokenIndex);

    //TODO:
    //template<>
    //const std::string& Tokenizer<std::wstring, delimiterT>::operator[](size_t tokenIndex);
};

template<class stringT, class delimiterT>
inline const std::string & Tokenizer<stringT, delimiterT>::operator[](size_t tokenIndex)
{
    return emptyString;
}

What is the proper specialization definition of Tokenizer<>::operator[]?

I'm receiving the following errors with this implementation: Errors

CodePudding user response:

As your operator[] is not a template, you can't specialize it inside your class. What you want is to specialize the non template method for a template class.

But you can't do a partial specialization for the class to add definitions of members to it.

Working example:

template <class stringT = std::string, class delimiterT = char>
class Tokenizer
{
    const std::string& operator[](size_t tokenIndex);
};

template<>
inline const std::string& Tokenizer<std::wstring, char>::operator[](size_t )
{
    return emptyString;
}
template< >
inline const std::string& Tokenizer<std::string, char>::operator[](size_t )
{
    return emptyString;
}

To get rid of that problem you should check if your method really depends on all template parameters. If not, you can simply put them to a base class, which only depends on a single template parm and inherit from there. Maybe other code organization may also help.

  • Related