专门用于任意类型矢量的模板

时间:2015-07-05 21:04:24

标签: c++ templates vs-unit-testing-framework

我有一个模板函数,用于将对象转换为字符串(这是来自库,我不能改变它):

template <typename Q> std::wstring ToString(const Q& q) { static_assert(false, "Must specialise"); }

现在,我想用std::vector<Gene>参数调用它,其中Gene是一个简单的类,其详细信息并不重要。当然,要做到这一点,我需要专门化模板,所以我做:

template<> std::wstring ToString(const std::vector<Gene>& q){...}

假设我有另一个班级Cell,我想专门针对ToString的{​​{1}}函数。我必须使用与std::vector<Cell>版本相同的主体进行另一个明确的专门化。

转换std::vector<Gene>的逻辑不依赖于实际的内容类型(int,std::vectorGene,其他Cell等),因此创建一个可以与任何std::vector一起使用的模板专业化是有意义的。但我无法找到一种简单的方法来做到这一点。目前,我目前有一个std::vector功能,并转发来自VectorToStringToString(std::vector<Gene>>)的来电,但这仍然要求我为每种元素类型实施专门化。

那么,对于实际的问题:是否可以为任意ToString(std::vector<Cell>)创建单一的专业化,我将如何做到这一点?而且,作为一个奖金问题,这可以推广到任何支持std::vectorstd::begin的任意集合吗?

我看过这个this question并试图宣布这样的专业化:

std::end

但这与C2768失败:非法使用显式模板参数(&#34;编译器无法确定函数定义是否应该是函数模板的显式特化,或者函数定义是否应该是对于一个新的功能。&#34;),这是有道理的,因为我们有相同的功能名称和模板参数的数量,以及类似的签名。

供参考,我使用的是Visual C ++ 2015 RC,原始模板函数来自本机测试库。

3 个答案:

答案 0 :(得分:2)

你差不多正确地做了但是如果你不应该把它们专门化,你应该像这样重载它们:

template <typename Q> std::wstring ToString(const Q& q) {
    return L"Original";
}
template<typename E> std::wstring ToString(const std::vector<E>& t) {
    return L"overload";
}

请参阅http://ideone.com/G3r0Vt了解正在运行的示例。

这是有效的,因为在选择要调用的重载时,const std::vector<E>被认为比const Q&“更好”,因此使用了重载。

在代码中使用这些方法时,您应该考虑ADL

答案 1 :(得分:2)

我有下一个例子给你。尝试使用下一个:

template<typename E> std::string ToString(const std::vector<E>& t)
{
    std::stringstream resStr;
    for (const E& element : t)
    {
        resStr << element << " ";
    }
    return resStr.str();
}

int _tmain(int argc, _TCHAR* argv[])
{
    std::vector<int> v1;
    v1.push_back(22);
    v1.push_back(33);
    std::vector<double> v2;
    v2.push_back(54.656);
    v2.push_back(44.656);
    auto strInt = ToString(v1);
    auto strDouble = ToString(v2);
    return 0;
}

答案 2 :(得分:0)

我将以下内容用于基类型的向量:

namespace Microsoft
{
    namespace VisualStudio
    {
        namespace CppUnitTestFramework
        {
            template<typename E>
            std::wstring ToString(const std::vector<E> & t)
            {
                std::wstringstream result;
                result << L"Size: " << t.size();

                if (t.size())
                {
                    result << L", Elements: ";

                    for (const auto & element : t)
                    {
                        result << L"{ " << element << L" } ";
                    }
                }
                return result.str();
            }
        }
    }
}

对于失败的测试,您可以清楚地看到矢量的大小及其包含的元素。为了您的目的,您可以使用:

namespace Microsoft
{
    namespace VisualStudio
    {
        namespace CppUnitTestFramework
        {
            template<typename E>
            std::wstring ToString(const std::vector<E> & t)
            {
                return L"Size: " + std::to_wstring(t.size());
            }
        }
    }
}