【问题标题】:C++ function with template template argument fail template argument deduction/substitution带有模板模板参数的 C++ 函数失败模板参数推导/替换
【发布时间】:2015-02-27 16:39:18
【问题描述】:

我正在尝试使用模板模板参数为 C++ STL 容器编写通用幂集函数。问题归结为以下模板参数推导/替换失败:

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:

【问题讨论】:

  • @Praetorian 注意 C 和 T 在函数调用中明确指定。
  • @jrok 是的,没仔细看问题,只看了函数签名
  • This 可能会回答您的问题。

标签: c++ templates template-templates template-argument-deduction


【解决方案1】:

如果您将签名更改为带有可变参数列表的模板参数

template <typename T, template<typename...> class C>
//                             ^^^^^^^^^^^
C<C<T>> getPowerSet(typename C<T>::iterator begin, typename C<T>::iterator end)

您不再需要将分配器类型添加到调用中。

【讨论】:

    【解决方案2】:

    朋友通过电子邮件向我发送了以下 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;
        }
        */
    }
    

    【讨论】:

      猜你喜欢
      • 2018-04-28
      • 2014-09-22
      • 1970-01-01
      • 2019-07-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-05
      相关资源
      最近更新 更多