可变参数模板的初始化没有匹配的构造函数 class
No matching constructor for initialization of variadic template class
我正在尝试为 Miranda Conrado 提供的笛卡尔积迭代器编写一个包装器 class(源代码可以在 GitHub 上找到)。为了方便起见,我也会在这里引用相关的代码。
我的 class 可以用两种方式构造 - 一种直接,通过将容器转发给 product_iterator
构造函数,另一种有点棘手:它需要一些元组来描述linspace 需要创建容器,然后从中构造迭代器。我就是在这里打了 dead-end.
这是一些代码。
首先,Conrado 的 class product_iterator
:
中的一些相关 headers
// product_iterator.hpp
template <class... Containers>
class product_iterator:
...
public:
product_iterator();
product_iterator(product_iterator const& other);
product_iterator(Containers const&... containers);
~product_iterator();
product_iterator const& operator=(product_iterator const& other);
....
};
template <class... Containers>
product_iterator<Containers...>
make_product_iterator(Containers const&... containers) {
return product_iterator<Containers...>(containers...);
}
这是我的 class:
// gridsearch.hpp
typedef std::unordered_map<std::string, Real> result_type;
typedef std::vector<result_type> resultgrid_type;
template <class... Containers>
class GridSearchIterator {
typedef std::array<std::string,
std::tuple_size<std::tuple<Containers...> >::value>
argname_type;
public:
GridSearchIterator() : product_it(product_iterator<Containers...>()),
argnames(argname_type()) {}
GridSearchIterator(const argname_type& names,
const Containers& ...containers);
template <class... TupleTypes>
static GridSearchIterator<Containers...>
initWith(const TupleTypes&& ...tuples);
template<class F, class... Args>
decltype(auto) iterate(F func, Args&&... params);
private:
template <typename TupleType, size_t... Is>
void product_impl(TupleType&& tuples, std::index_sequence<Is...>);
template <typename TupleType>
const auto& unpack_tuple(TupleType& t, size_t index);
product_iterator<Containers...> product_it;
argname_type argnames;
};
// implementation:
template <class... Containers>
GridSearchIterator<Containers...>::GridSearchIterator(
const argname_type& names,
const Containers& ...containers):
product_it(product_iterator<Containers...>(containers...)),
argnames(names) {}
template <class... Containers>
template <typename... TupleTypes>
GridSearchIterator<Containers...> GridSearchIterator<Containers...>::initWith(const TupleTypes&& ...tuples)
{
GridSearchIterator<Containers...> gsi =
GridSearchIterator<Containers...>();
gsi.product_impl(std::tuple<TupleTypes...>(tuples...),
std::index_sequence_for<TupleTypes...>{});
return gsi;
}
template <class... Containers>
template <typename TupleType, size_t... Is>
void GridSearchIterator<Containers...>::product_impl(TupleType&& tuples,
std::index_sequence<Is...>)
{
product_it = product_iterator<Containers...>(
unpack_tuple(std::get<Is>(tuples), Is)...);
// this is where the problem is; Compiler claims No matching constructor for initialization of 'product_iterator...
}
template <class... Containers>
template <typename TupleType>
const auto& GridSearchIterator<Containers...>::unpack_tuple(TupleType &t,
size_t index)
{
std::string argname;
auto left(0), right(0);
Size step;
std::tie(argname, left, right, step) = t;
argnames[index] = argname;
auto vec = linspace(left, right, step);
return static_cast<const decltype(vec) &>(vec);
}
linspace
上面的函数 returns 一个从 left
到 right
的数字矢量,按 step
的数量均匀分布。它等效于 Numpy 函数 np.linspace
.
我检查过,对 unpack_tuple()
的调用确实产生了初始化 product_iterator
所需的向量,但编译器不同意。我的猜测是 unpack_tuple()
返回的类型与 product_iterator
构造函数所期望的类型有些不同,但我无法弄清楚问题出在哪里。或者,也许问题实际上完全出在其他地方。
为了更好地理解,下面是我如何使用 class:
{
...
typedef std::tuple<std::string, int, int, size_t> inttuple;
typedef std::tuple<std::string, double, double, size_t> realtuple;
typedef std::vector<int> intvector;
typedef std::vector<Real> realvector;
inttuple sidespan = std::make_tuple("side",1,1,1);
real tuple takeprofit = std::make_tuple("takeprofit",1.,2.,2);
real tuple stoploss = std::make_tuple("stoploss", -1.,-3.,3);
inttuple period = std::make_tuple("horizon", 100, 100, 1);
auto grid_iter = GridSearchIterator<intvector, realvector, realvector, intvector>
::initWith(std::forward<inttuple>(sidespan),
std::forward<realtuple>(takeprofit),
std::forward<realtuple>(stoploss),
std::forward<inttuple>(period));
...
}
我花了几个小时试图解决它,因此我们将不胜感激任何帮助或指点,包括对不同实施的建议。
更新
抱歉,我以为我昨天更新了我的问题,但由于某种原因没有保存更改。
无论如何,即使没有其他信息,@max66 也回答了这个问题。尽管如此,为了完整起见,这里是 linspace()
定义
template <typename T>
std::vector<T> linspace(T a, T b, size_t N)
和编译器消息:
In file included from /.../main.cpp:17:
/.../gridsearch.hpp:98:18: error: no matching constructor for initialization of 'product_iterator<std::__1::vector<int, std::__1::allocator<int> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<int, std::__1::allocator<int> > >'
product_it = product_iterator<Containers...>(unpack_tuple(std::get<Is>(tuples), Is)...);
/.../gridsearch.hpp:91:9: note: in instantiation of function template specialization 'GridSearchIterator<std::__1::vector<int, std::__1::allocator<int> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<int, std::__1::allocator<int> > >::product_impl<std::__1::tuple<std::__1::tuple<std::__1::basic_string<char>, int, int, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, double, double, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, double, double, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, int, int, unsigned long> >, 0, 1, 2, 3>'
requested here gsi.product_impl(std::tuple<TupleTypes...>(tuples...), std::index_sequence_for<TupleTypes...>{});
/.../main.cpp:90:88: note: in instantiation of function template specialization 'GridSearchIterator<std::__1::vector<int, std::__1::allocator<int> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<int, std::__1::allocator<int> > >::initWith<std::__1::tuple<std::__1::basic_string<char>, int, int, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, double, double, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, double, double, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, int, int, unsigned long> >'
requested here auto grid_iter = GridSearchIterator<intvector, realvector, realvector, intvector>::initWith(std::forward<inttuple>(sidespan),
In file included from /.../main.cpp:17:
In file included from /.../gridsearch.hpp:22:
/.../product_iterator.hpp:73:7: note: candidate constructor not viable: no known conversion from 'vector<int, allocator<int>>' to 'const vector<double, allocator<double>>'
for 2nd argument product_iterator(Containers const&... containers);
如果您不提供完整的示例,就很难check/verify/propose一个正确的代码。
无论如何你在这行有错误("no matching constructor")
product_it = product_iterator<Containers...>(
unpack_tuple(std::get<Is>(tuples), Is)...);
其中,如果我没理解错的话,Containers...
就是 intvector, realvector, realvector, intvector
a.k.a。 std::vector<int>, std::vector<Real>, std::vector<Real>, std::vector<int>
(我认为 Real
是 double
的别名)。
product_iterator
的唯一可变参数构造函数是接收 Containers const&... containers
的构造函数,所以我想这就是您要匹配的构造函数。
在我看来问题是 unpack_tuple()
template <class... Containers>
template <typename TupleType>
const auto& GridSearchIterator<Containers...>::unpack_tuple(TupleType &t,
size_t index)
{
std::string argname;
auto left(0), right(0);
Size step;
std::tie(argname, left, right, step) = t;
argnames[index] = argname;
auto vec = linspace(left, right, step);
return static_cast<const decltype(vec) &>(vec);
}
return 曾经一个intVector const &
(std::vector<int> const &
)。当用 realVector
调用时(我想是 std::vector<double>
)。
这(如果我没记错的话)是因为您将 left
和 right
定义为 auto
并使用 int
初始化它们
auto left(0), right(0);
当 TupleType
在第二和第三位置包含 Real
个元素时,您也会得到几个 int
。
所以当你获得vec
auto vec = linspace(left, right, step);
你获得(我想)一个 std::vector<int>
;曾经;还有当你应该获得 std::vector<Real>
.
建议:使用依赖于 TupleType
.
的正确类型定义 left
和 right
通过示例(注意:代码未经测试)
using lr_type = typename std::tuple_element<1u, TupleType>::type;
lr_type left, right;
从 C++14 开始你可以使用 std::tuple_element_t
`using 可以简化如下
using lr_type = std::tuple_element_t<1u, TupleType>;
如果能用C++17,就可以用结构化绑定,一切都变得简单很多
template <typename TupleType>
const auto& GridSearchIterator<Containers...>::unpack_tuple(TupleType &t,
size_t index)
{
auto [argname, left, right, step] = t;
argnames[index] = argname;
auto vec = linspace(left, right, step);
return static_cast<const decltype(vec) &>(vec);
}
题外话:你确定这是个好主意吗unpack_tuple()
return将 constreference 指向一个在结束时销毁的值方法的执行 ?
我正在尝试为 Miranda Conrado 提供的笛卡尔积迭代器编写一个包装器 class(源代码可以在 GitHub 上找到)。为了方便起见,我也会在这里引用相关的代码。
我的 class 可以用两种方式构造 - 一种直接,通过将容器转发给 product_iterator
构造函数,另一种有点棘手:它需要一些元组来描述linspace 需要创建容器,然后从中构造迭代器。我就是在这里打了 dead-end.
这是一些代码。
首先,Conrado 的 class product_iterator
:
// product_iterator.hpp
template <class... Containers>
class product_iterator:
...
public:
product_iterator();
product_iterator(product_iterator const& other);
product_iterator(Containers const&... containers);
~product_iterator();
product_iterator const& operator=(product_iterator const& other);
....
};
template <class... Containers>
product_iterator<Containers...>
make_product_iterator(Containers const&... containers) {
return product_iterator<Containers...>(containers...);
}
这是我的 class:
// gridsearch.hpp
typedef std::unordered_map<std::string, Real> result_type;
typedef std::vector<result_type> resultgrid_type;
template <class... Containers>
class GridSearchIterator {
typedef std::array<std::string,
std::tuple_size<std::tuple<Containers...> >::value>
argname_type;
public:
GridSearchIterator() : product_it(product_iterator<Containers...>()),
argnames(argname_type()) {}
GridSearchIterator(const argname_type& names,
const Containers& ...containers);
template <class... TupleTypes>
static GridSearchIterator<Containers...>
initWith(const TupleTypes&& ...tuples);
template<class F, class... Args>
decltype(auto) iterate(F func, Args&&... params);
private:
template <typename TupleType, size_t... Is>
void product_impl(TupleType&& tuples, std::index_sequence<Is...>);
template <typename TupleType>
const auto& unpack_tuple(TupleType& t, size_t index);
product_iterator<Containers...> product_it;
argname_type argnames;
};
// implementation:
template <class... Containers>
GridSearchIterator<Containers...>::GridSearchIterator(
const argname_type& names,
const Containers& ...containers):
product_it(product_iterator<Containers...>(containers...)),
argnames(names) {}
template <class... Containers>
template <typename... TupleTypes>
GridSearchIterator<Containers...> GridSearchIterator<Containers...>::initWith(const TupleTypes&& ...tuples)
{
GridSearchIterator<Containers...> gsi =
GridSearchIterator<Containers...>();
gsi.product_impl(std::tuple<TupleTypes...>(tuples...),
std::index_sequence_for<TupleTypes...>{});
return gsi;
}
template <class... Containers>
template <typename TupleType, size_t... Is>
void GridSearchIterator<Containers...>::product_impl(TupleType&& tuples,
std::index_sequence<Is...>)
{
product_it = product_iterator<Containers...>(
unpack_tuple(std::get<Is>(tuples), Is)...);
// this is where the problem is; Compiler claims No matching constructor for initialization of 'product_iterator...
}
template <class... Containers>
template <typename TupleType>
const auto& GridSearchIterator<Containers...>::unpack_tuple(TupleType &t,
size_t index)
{
std::string argname;
auto left(0), right(0);
Size step;
std::tie(argname, left, right, step) = t;
argnames[index] = argname;
auto vec = linspace(left, right, step);
return static_cast<const decltype(vec) &>(vec);
}
linspace
上面的函数 returns 一个从 left
到 right
的数字矢量,按 step
的数量均匀分布。它等效于 Numpy 函数 np.linspace
.
我检查过,对 unpack_tuple()
的调用确实产生了初始化 product_iterator
所需的向量,但编译器不同意。我的猜测是 unpack_tuple()
返回的类型与 product_iterator
构造函数所期望的类型有些不同,但我无法弄清楚问题出在哪里。或者,也许问题实际上完全出在其他地方。
为了更好地理解,下面是我如何使用 class:
{
...
typedef std::tuple<std::string, int, int, size_t> inttuple;
typedef std::tuple<std::string, double, double, size_t> realtuple;
typedef std::vector<int> intvector;
typedef std::vector<Real> realvector;
inttuple sidespan = std::make_tuple("side",1,1,1);
real tuple takeprofit = std::make_tuple("takeprofit",1.,2.,2);
real tuple stoploss = std::make_tuple("stoploss", -1.,-3.,3);
inttuple period = std::make_tuple("horizon", 100, 100, 1);
auto grid_iter = GridSearchIterator<intvector, realvector, realvector, intvector>
::initWith(std::forward<inttuple>(sidespan),
std::forward<realtuple>(takeprofit),
std::forward<realtuple>(stoploss),
std::forward<inttuple>(period));
...
}
我花了几个小时试图解决它,因此我们将不胜感激任何帮助或指点,包括对不同实施的建议。
更新
抱歉,我以为我昨天更新了我的问题,但由于某种原因没有保存更改。
无论如何,即使没有其他信息,@max66 也回答了这个问题。尽管如此,为了完整起见,这里是 linspace()
定义
template <typename T>
std::vector<T> linspace(T a, T b, size_t N)
和编译器消息:
In file included from /.../main.cpp:17:
/.../gridsearch.hpp:98:18: error: no matching constructor for initialization of'product_iterator<std::__1::vector<int, std::__1::allocator<int> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<int, std::__1::allocator<int> > >' product_it = product_iterator<Containers...>(unpack_tuple(std::get<Is>(tuples), Is)...);
/.../gridsearch.hpp:91:9: note: in instantiation of function template specialization
'GridSearchIterator<std::__1::vector<int, std::__1::allocator<int> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<int, std::__1::allocator<int> > >::product_impl<std::__1::tuple<std::__1::tuple<std::__1::basic_string<char>, int, int, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, double, double, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, double, double, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, int, int, unsigned long> >, 0, 1, 2, 3>'
requested heregsi.product_impl(std::tuple<TupleTypes...>(tuples...), std::index_sequence_for<TupleTypes...>{});
/.../main.cpp:90:88: note: in instantiation of function template specialization
'GridSearchIterator<std::__1::vector<int, std::__1::allocator<int> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<double, std::__1::allocator<double> >, std::__1::vector<int, std::__1::allocator<int> > >::initWith<std::__1::tuple<std::__1::basic_string<char>, int, int, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, double, double, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, double, double, unsigned long>, std::__1::tuple<std::__1::basic_string<char>, int, int, unsigned long> >'
requested hereauto grid_iter = GridSearchIterator<intvector, realvector, realvector, intvector>::initWith(std::forward<inttuple>(sidespan),
In file included from /.../main.cpp:17:
In file included from /.../gridsearch.hpp:22: /.../product_iterator.hpp:73:7: note: candidate constructor not viable: no known conversion from'vector<int, allocator<int>>' to 'const vector<double, allocator<double>>'
for 2nd argumentproduct_iterator(Containers const&... containers);
如果您不提供完整的示例,就很难check/verify/propose一个正确的代码。
无论如何你在这行有错误("no matching constructor")
product_it = product_iterator<Containers...>(
unpack_tuple(std::get<Is>(tuples), Is)...);
其中,如果我没理解错的话,Containers...
就是 intvector, realvector, realvector, intvector
a.k.a。 std::vector<int>, std::vector<Real>, std::vector<Real>, std::vector<int>
(我认为 Real
是 double
的别名)。
product_iterator
的唯一可变参数构造函数是接收 Containers const&... containers
的构造函数,所以我想这就是您要匹配的构造函数。
在我看来问题是 unpack_tuple()
template <class... Containers>
template <typename TupleType>
const auto& GridSearchIterator<Containers...>::unpack_tuple(TupleType &t,
size_t index)
{
std::string argname;
auto left(0), right(0);
Size step;
std::tie(argname, left, right, step) = t;
argnames[index] = argname;
auto vec = linspace(left, right, step);
return static_cast<const decltype(vec) &>(vec);
}
return 曾经一个intVector const &
(std::vector<int> const &
)。当用 realVector
调用时(我想是 std::vector<double>
)。
这(如果我没记错的话)是因为您将 left
和 right
定义为 auto
并使用 int
auto left(0), right(0);
当 TupleType
在第二和第三位置包含 Real
个元素时,您也会得到几个 int
。
所以当你获得vec
auto vec = linspace(left, right, step);
你获得(我想)一个 std::vector<int>
;曾经;还有当你应该获得 std::vector<Real>
.
建议:使用依赖于 TupleType
.
left
和 right
通过示例(注意:代码未经测试)
using lr_type = typename std::tuple_element<1u, TupleType>::type;
lr_type left, right;
从 C++14 开始你可以使用 std::tuple_element_t
`using 可以简化如下
using lr_type = std::tuple_element_t<1u, TupleType>;
如果能用C++17,就可以用结构化绑定,一切都变得简单很多
template <typename TupleType>
const auto& GridSearchIterator<Containers...>::unpack_tuple(TupleType &t,
size_t index)
{
auto [argname, left, right, step] = t;
argnames[index] = argname;
auto vec = linspace(left, right, step);
return static_cast<const decltype(vec) &>(vec);
}
题外话:你确定这是个好主意吗unpack_tuple()
return将 constreference 指向一个在结束时销毁的值方法的执行 ?