C ++模板与STL返回类型相结合

时间:2011-12-06 11:28:05

标签: c++ templates stl map overloading

我有一个模板化的课程

template <typename T>
class Factors
{
    public:
    Factors(){};
    deque<string> stringsDeck;

    // some methods and variables here
   map <string, string> getNext();
};

getNext方法将用作键的字符串与用作值的stringsDeck字符串组合在一起,并返回map <string,string>。 如果我已经模板化stringifystring2num函数,我希望有一个方法map<string,Scalar> getNext(),除了字符串之外的其他每种类型都会将地图的值转换为指定的模板类型T

编译器不允许我重载具有相同名称但具有不同返回类型的两个方法,具体为:

map <string, T > getNext()
{
// converts the values of getNext() return map into the specified type T
return convertedMapWithValuesOfTypeT;
}

在这种情况下可以解决什么问题?我想保持方法的名称与字符串和其他类型相同(基本上是可以通过词法转换从字符串转换的数字类型)

2 个答案:

答案 0 :(得分:4)

语言不允许功能过载,这些功能只有不同 返回类型,因为在大多数情况下,不考虑返回类型 功能重载决议。在这种情况下,你真的有三个 可能的解决方案:

  • 最简单的(因此在大多数情况下是首选解决方案)是 只是给两个函数不同的名字: getNextAsMapToType和 例如getNextAsMapToString
  • 或者,您可以将该函数声明为模板:
    template<typename U>
    std::map<string, U> getNext();
    
    然后,将此函数专门用于std::stringT(和 没有其他的)。用户必须指定 getNext<std::string>()getNext<...>给他想要的人打电话。 一般来说,我会发现它的可读性远远低于 以前的解决方案,但它可能适用于模板,其中 名称应包含或至少建议类型的名称。
  • 最后,它可以在返回时模拟重载 类型,如果你不介意一些额外的复杂性。要做到这一点,你仍然 必须实现其他解决方案之一,但客户端代码 没有看到它。基本上,您的getNext()函数必须返回一个 代理,具有重载转换函数,类似于:
    class Proxy
    {
        Factors* myOwner;
    public:
        Proxy( Factors& owner ) : myOwner( &owner ) {}
        operator std::map<std::string, std::string>() const
        {
            return myOwner->getNextAsMapToString();
        }
        operator std::map<std::string, T>() const
        {
            return myOwner->getNextAsMapToType();
        }
    };
    
    Proxy getNext() { return Proxy( *this ); }
    
    然后,客户端代码可以只调用getNext(),具体取决于它们 做结果,getNextAsMapToStringgetNextAsMapToType将被调用。

答案 1 :(得分:0)

您可以使用[getNext]在typeid中添加运行时检查 (http://en.cppreference.com/w/cpp/language/typeid)查看T是否为字符串。

类似的东西:

template <typename T>
class Factors
{
    public:
    Factors(){};
    deque<string> stringsDeck;

    // some methods and variables here
    map <string, T> getNext();
    {
        if (typeid(T) == typeid(string))
        {
            // Special handling for strings
        }
        else
        {
            // Do something else for other types
        }
    }
};

修改

正如fschoenm所说,模板专业化可能更好:

template <typename T>
class Factors
{
    public:
    Factors(){};

    // some methods and variables here
    map <string, T> getNext();
};


template <>
class Factors<string>
{
    public:
    Factors(){};
    deque<string> stringsDeck;

    // some methods and variables here
    map <string, string> getNext();
};