如何在c ++中使用嵌套模板?

时间:2019-07-06 16:18:57

标签: c++ templates

我是C ++的新手,现在开始在C ++中上课。作为作业,我们应该编写一个函数,该函数接受任何容器作为输入,但不使用迭代器。因此,不允许我们仅传递std::begin(container)std::end(container)作为参数。我们必须通过容器作为参考。我对此的看法是以下函数声明:

template <typename T, typename U, typename V, template <typename a, typename b> typename container>
void doStuff(container<T, U>& first, container<T, V>& second)
{
    // the code
}

它接受两个容器(或使用两个模板参数的任何模板化类型)。 container中的第二个模板参数是不同的,因为数组V中的数组可能代表数组的大小,我希望能够接受两个大小不同的数组。

示例:

std::array<bool, 4> a1 = { true, false, false, false };
std::array<bool, 1> a2 = { false };

不幸的是,此示例不起作用。该错误表明我doStuff不接受这些类型的参数。这是为什么?

我认为,在这里使用“模板化模板”非常重要,因为我想确保该函数仅在两个容器包含相同类型的数据时才接受它们。因此,传递int数组和double数组不起作用。

1 个答案:

答案 0 :(得分:3)

如果要支持尽可能多的容器类型,则应使用限制最小的定义:

    static void Main(string[] args)
    {
        string a = "AAA";
        using (WebClient wc = new WebClient())
        {
            wc.DownloadStringCompleted += Wc_DownloadStringCompleted;
            wc.DownloadStringAsync(new Uri("http://someurl.to.json"), a);
        }
        Console.ReadKey();
        Console.WriteLine(a);
    }

    private static void Wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
    {
        // do something with e.result ...;
        // update the caller method's 'a' variable (by ref not possible as token) with "BBB"
    }

这是因为容器类型具有各种风味,例如template <typename FirstContainer, typename SecondContainer> void doStuff(FirstContainer& first, SecondContainer& second) { } 是一个使用值类型和静态大小作为参数的模板,std::array是一个使用值类型和分配器的模板,某些自定义std::vector可能根本不是模板。

您的实现可能对受支持的容器有一些特定要求,例如它可能仅适用于整数类型的容器。但是通常,这只是实现的隐式结果。以一个简单的函数为例,该函数将两个容器的值相加:

StringList

此函数对可以添加到整数的任何值类型均适用。如果无法添加(例如template <typename FirstContainer, typename SecondContainer> int sum(const FirstContainer& first, const SecondContainer& second) { int result = 0; for (auto value : first) result += value; for (auto value : second) result += value; return result; } ),最终将导致编译错误。

(请注意,可以使用自动推断的总和类型而不只是std::string来编写此函数,甚至更通用)

如果这些“隐式要求”不足以满足您的需求,则可以使用int添加显式检查:

static_assert

现在,您的函数仅接受包含普通template <typename FirstContainer, typename SecondContainer> int sum(const FirstContainer& first, const SecondContainer& second) { int result = 0; for (auto value : first) { static_assert(std::is_same_v<int, decltype(value)>, "FirstContainer does not hold integers"); result += value; } for (auto value : second) { static_assert(std::is_same_v<int, decltype(value)>, "SecondContainer does not hold integers"); result += value; } return result; } 的容器,而没有其他内容。

您也可以使用int完全“禁用”不受支持的容器的功能:

std::enable_if

现在,您的函数仅限于使用嵌套typedef template <typename FirstContainer, typename SecondContainer> auto sum(const FirstContainer& first, const SecondContainer& second) -> std::enable_if_t< std::is_same_v<typename FirstContainer::value_type, int> && std::is_same_v<typename SecondContainer::value_type, int>, int > { int result = 0; for (auto value : first) result += value; for (auto value : second) result += value; return result; } 来键入value_type的容器。