gpt4 book ai didi

c++ - 模板模板参数的模板参数推导错误

转载 作者:太空宇宙 更新时间:2023-11-04 12:46:59 28 4
gpt4 key购买 nike

我在编写非模板类的模板成员时遇到问题,特别是在推导模板模板参数的模板参数时。

以下代码(最小)说明了我的问题。我怀疑那里至少有两个不同的问题。

#include <iostream>
#include <list>

using namespace std;

struct A
{
list<int> l;

template<template<class> class Iterable>
A(Iterable<int>& it);
};

template<template<class> class Iterable>
A::A(Iterable<int>& it) : l(list<int>())
{
for(int i : it)
l.push_back(i);
}

int main()
{
list<int> l = {1, 2, 3, 4};
A a(l);
for(int i : a.l)
cout << i << " ";
cout << endl;

A b = {1, 2, 3, 4};
for(int i : b.l)
cout << i << " ";
cout << endl;
}

备注:我真的很想提供课外的定义。我还希望 A 的构造函数的原型(prototype)能够处理整数列表、整数 vector 以及初始化列表。

最佳答案

I suspect there are at least two different problems down there.

正确:我看到三个不同的问题。

1) std::list需要两个模板参数;第二个是默认值( std::allocator<T> ,其中 T 是第一个模板参数);以及 vectors、deques、sets 等需要更多的模板参数(有些是默认的)。

所以 template<template<class> class>不匹配 std::list和其他 STL 容器。

为了更通用,我建议如下

template <template <typename...> class Iterable, typename ... Ts> 
A (Iterable<int, Ts...> & it);

2) A b = {1, 2, 3, 4};不起作用,因为您正在调用带有四个参数的构造函数,而您只有一个带有一个参数的构造函数。所以你必须用一些东西来明确容器

A b = std::list<int>{1, 2, 3, 4};

鉴于您期望std::initializer_list作为默认容器,如果您接受将图形加倍( { { 1, 2, 3, 4 } } ,而不是 { 1, 2, 3, 4 } ,以将单个参数传递给构造函数),您可以指示 std::initializer_list (或其他容器,如果您愿意)默认为 Iterable .

我的意思是...如果你声明构造函数如下

   template <template <typename...> class Iterable = std::initializer_list,
typename ... Ts>
A (Iterable<int, Ts...> const & it);

然后你可以初始化b作为

   A b {{1, 2, 3, 4}};

3) 签名Iterable<int, Ts...> & it , 在你的模板构造函数中,接受一个左值引用,所以接受

list<int> l = {1, 2, 3, 4};
A a(l);

但不接受

A b = std::list<int>{1, 2, 3, 4};

因为std::list<int>{1, 2, 3, 4}是一个 r 值。

要解决这个问题,您可以为 r 值引用编写一个不同的构造函数,但在这种情况下,我怀疑这是可以接受的,只需修改模板构造使其能够接受 const l-值(value)引用

A (Iterable<int, Ts...> const & it); 
// .....................^^^^^

额外的(离题)建议:如果您有兴趣接受 STL 容器,您可以使用 l 来简化您的模板构造器。接受几个迭代器( begin() , end() )的构造函数,所以

template <template <typename...> class Iterable, typename ... Ts>
A::A (Iterable<int, Ts...> const & it) : l{it.cbegin(), it.cend()}
{ }

或者还有

template <template <typename...> class Iterable, typename ... Ts>
A::A (Iterable<int, Ts...> const & it) : l{std::cbegin(it), std::cend(it)}
{ }

以下是你修改的代码

#include <initializer_list>
#include <iostream>
#include <list>

struct A
{
std::list<int> l;

template <template <typename...> class Iterable = std::initializer_list,
typename ... Ts>
A (Iterable<int, Ts...> const & it);
};

template <template <typename...> class Iterable, typename ... Ts>
A::A (Iterable<int, Ts...> const & it) : l{std::cbegin(it), std::cend(it)}
{ }

int main ()
{
std::list<int> l {1, 2, 3, 4};
A a(l);

for (auto i : a.l)
std::cout << i << " ";
std::cout << std::endl;

A b {{1, 2, 3, 4}};

for (auto i : b.l)
std::cout << i << " ";
std::cout << std::endl;
}

关于c++ - 模板模板参数的模板参数推导错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51017536/

28 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com