带有模板模板参数的 C++ 函数失败模板参数 deduction/substitution
C++ function with template template argument fail template argument deduction/substitution
我正在尝试使用模板参数为 C++ STL 容器编写通用幂集函数。问题归结为以下模板参数 deduction/substitution 失败:
template <typename T, template<typename> class C>
C<C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)
...
vector<vector<int>> powerSet = getPowerSet<int, vector>(set.begin(), set.end());
代码和编译器错误(使用 g++ (GCC) 4.8.1 20130531 (Red Hat 4.8.1-1))如下。我注释掉了与编译器错误无关的部分。
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;
template <typename T, template<typename> class C>
C<C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)
{
C<C<T>> powerSet;
/*
if (begin == end)
return powerSet;
C<C<T>> subproblem = getPowerSet(begin + 1, end);
copy(subproblem.begin(), subproblem.end(), inserter(powerSet, powerSet.end()));
for (C<T> set : subproblem)
{
*inserter(set, set.begin()) = *begin;
}
copy(subproblem.begin(), subproblem.end(), inserter(powerSet, powerSet.end()));
*/
return powerSet;
}
int main()
{
vector<int> set;
for(int i = 0; i < 5; ++i)
set.push_back(i);
vector<vector<int>> powerSet = getPowerSet<int, vector>(set.begin(), set.end());
/*
for (auto set : powerSet)
{
for (int elem : set)
{
cout << elem << " ";
}
cout << endl;
}
*/
}
编译错误如下:
[thomas.bao@cwdev01 recursion]$ g++ 3.cpp
3.cpp:8:15: error: template argument 1 is invalid
C<typename C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)
^
3.cpp: In function ‘int main()’:
3.cpp:31:83: error: no matching function for call to ‘getPowerSet(std::vector<int>::iterator, std::vector<int>::iterator)’
vector<vector<int>> powerSet = getPowerSet<int, vector>(set.begin(), set.end());
^
3.cpp:31:83: note: candidate is:
3.cpp:8:18: note: template<class T, template<class> class C> int getPowerSet(typename C<T>::iterator, typename C<T>::iterator)
C<typename C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)
^
3.cpp:8:18: note: template argument deduction/substitution failed:
朋友通过电子邮件向我发送了以下内容 gem(该死的默认模板参数):
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;
template <typename T, typename S, template<typename, typename> class C>
C<C<T, S>, std::allocator<C<T, S> > > getPowerSet(typename C<T, S>::iterator begin, typename C<T, S>::iterator end)
{
C<C<T, S>, std::allocator<C<T, S> > > powerSet;
/*
if (begin == end)
return powerSet;
C<C<T>> subproblem = getPowerSet(begin + 1, end);
copy(subproblem.begin(), subproblem.end(), inserter(powerSet, powerSet.end()));
for (C<T> set : subproblem)
{
*inserter(set, set.begin()) = *begin;
}
copy(subproblem.begin(), subproblem.end(), inserter(powerSet, powerSet.end()));
*/
return powerSet;
}
int main()
{
vector<int> set;
for(int i = 0; i < 5; ++i)
set.push_back(i);
auto powerSet = getPowerSet<int, std::allocator<int>, vector>(set.begin(), set.end());
/*
for (auto set : powerSet)
{
for (int elem : set)
{
cout << elem << " ";
}
cout << endl;
}
*/
}
如果您更改签名以采用带有可变参数列表的模板参数
template <typename T, template<typename...> class C>
// ^^^^^^^^^^^
C<C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)
您不再需要将分配器类型添加到调用中。
我正在尝试使用模板参数为 C++ STL 容器编写通用幂集函数。问题归结为以下模板参数 deduction/substitution 失败:
template <typename T, template<typename> class C>
C<C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)
...
vector<vector<int>> powerSet = getPowerSet<int, vector>(set.begin(), set.end());
代码和编译器错误(使用 g++ (GCC) 4.8.1 20130531 (Red Hat 4.8.1-1))如下。我注释掉了与编译器错误无关的部分。
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;
template <typename T, template<typename> class C>
C<C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)
{
C<C<T>> powerSet;
/*
if (begin == end)
return powerSet;
C<C<T>> subproblem = getPowerSet(begin + 1, end);
copy(subproblem.begin(), subproblem.end(), inserter(powerSet, powerSet.end()));
for (C<T> set : subproblem)
{
*inserter(set, set.begin()) = *begin;
}
copy(subproblem.begin(), subproblem.end(), inserter(powerSet, powerSet.end()));
*/
return powerSet;
}
int main()
{
vector<int> set;
for(int i = 0; i < 5; ++i)
set.push_back(i);
vector<vector<int>> powerSet = getPowerSet<int, vector>(set.begin(), set.end());
/*
for (auto set : powerSet)
{
for (int elem : set)
{
cout << elem << " ";
}
cout << endl;
}
*/
}
编译错误如下:
[thomas.bao@cwdev01 recursion]$ g++ 3.cpp
3.cpp:8:15: error: template argument 1 is invalid
C<typename C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)
^
3.cpp: In function ‘int main()’:
3.cpp:31:83: error: no matching function for call to ‘getPowerSet(std::vector<int>::iterator, std::vector<int>::iterator)’
vector<vector<int>> powerSet = getPowerSet<int, vector>(set.begin(), set.end());
^
3.cpp:31:83: note: candidate is:
3.cpp:8:18: note: template<class T, template<class> class C> int getPowerSet(typename C<T>::iterator, typename C<T>::iterator)
C<typename C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)
^
3.cpp:8:18: note: template argument deduction/substitution failed:
朋友通过电子邮件向我发送了以下内容 gem(该死的默认模板参数):
#include <vector>
#include <iostream>
#include <iterator>
#include <algorithm>
using namespace std;
template <typename T, typename S, template<typename, typename> class C>
C<C<T, S>, std::allocator<C<T, S> > > getPowerSet(typename C<T, S>::iterator begin, typename C<T, S>::iterator end)
{
C<C<T, S>, std::allocator<C<T, S> > > powerSet;
/*
if (begin == end)
return powerSet;
C<C<T>> subproblem = getPowerSet(begin + 1, end);
copy(subproblem.begin(), subproblem.end(), inserter(powerSet, powerSet.end()));
for (C<T> set : subproblem)
{
*inserter(set, set.begin()) = *begin;
}
copy(subproblem.begin(), subproblem.end(), inserter(powerSet, powerSet.end()));
*/
return powerSet;
}
int main()
{
vector<int> set;
for(int i = 0; i < 5; ++i)
set.push_back(i);
auto powerSet = getPowerSet<int, std::allocator<int>, vector>(set.begin(), set.end());
/*
for (auto set : powerSet)
{
for (int elem : set)
{
cout << elem << " ";
}
cout << endl;
}
*/
}
如果您更改签名以采用带有可变参数列表的模板参数
template <typename T, template<typename...> class C>
// ^^^^^^^^^^^
C<C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)
您不再需要将分配器类型添加到调用中。