首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >模板参数参数的参数推导

模板参数参数的参数推导
EN

Stack Overflow用户
提问于 2014-02-03 17:55:13
回答 5查看 719关注 0票数 2

我有一个课程模板。在这个类模板中,我试图定义一个成员函数模板,它在string集合上接受string,集合本身可以是任何类型的StdLib集合,但实际上它要么是vector,要么是list

因为集合可以是任何类型,所以我使用一个template-template参数来指定集合类型。但是,它始终是string的集合。我希望模板参数演绎能够工作,这样我就不必在调用成员函数时指定集合类型。

下面的SSCCE代码类似于我的预期用例。

到目前为止,我已经对类定义(现场演示)进行了如下操作:

代码语言:javascript
复制
template <typename Foo>
struct Gizmo
{
    Foo mF;
    Gizmo (Foo f) : mF (f) {};

    template <template <typename> class Cont> void DoIt(
        typename Cont <string>::const_iterator begin,
        typename Cont <string>::const_iterator end)
        {
            stringstream ss;
            ss << "(" << this->mF << ")\n";
            const std::string s = ss.str();
            copy (begin, end, ostream_iterator <std::string> (cout, s.c_str()));
        }
};

类模板实例化的编译成功:

代码语言:javascript
复制
int main()
{
    list <string> l;
    l.push_back ("Hello");
    l.push_back ("world");

    Gizmo <unsigned> g (42);
}

然而,当我试图利用论点推断(没有它,整个练习几乎毫无意义):

代码语言:javascript
复制
g.DoIt (l.begin(), l.end());

GCC抱怨说,它无法推断模板参数:

代码语言:javascript
复制
prog.cpp: In function ‘int main()’:
prog.cpp:34:28: error: no matching function for call to ‘Gizmo<unsigned int>::DoIt(std::list<std::basic_string<char> >::iterator, std::list<std::basic_string<char> >::iterator)’
  g.DoIt (l.begin(), l.end());
                            ^
prog.cpp:34:28: note: candidate is:
prog.cpp:16:49: note: template<template<class> class typedef Cont Cont> void Gizmo<Foo>::DoIt(typename Cont<std::basic_string<char> >::const_iterator, typename Cont<std::basic_string<char> >::const_iterator) [with Cont = Cont; Foo = unsigned int]
  template <template <typename> class Cont> void DoIt(
                                                 ^
prog.cpp:16:49: note:   template argument deduction/substitution failed:
prog.cpp:34:28: note:   couldn't deduce template parameter ‘template<class> class typedef Cont Cont’
  g.DoIt (l.begin(), l.end());

最终,我真正关心的是能够在一个string集合上使用开始迭代器和结束迭代器调用string。实际的集合类型可以是vectorlist,我不想指定模板参数,也不想基于容器重载。

我怎么才能让这个起作用?

注意,我的实际用例将在C++03中。C++11解决方案是受欢迎的,但我只能接受C++03解决方案。

EN

回答 5

Stack Overflow用户

发布于 2014-02-03 18:37:52

有几个问题。我为您修复了模板参数。我还修改了方法签名,以便您可以自动推断类型,但它需要传入原始集合:

代码语言:javascript
复制
#include <iostream>
#include <vector>
#include <list>
#include <string>
#include <sstream>
#include <iterator>
using namespace std;


template <typename Foo>
struct Gizmo
{
    Foo mF;
    Gizmo (Foo f) : mF (f) {};

    template <template <typename T, typename A = allocator<T> > class Cont> void DoIt(
        const Cont <string> &, // deduction
        const typename Cont <string>::iterator &begin,
        const typename Cont <string>::iterator &end)
        {
            stringstream ss;
            ss << "(" << this->mF << ")\n";
            const std::string s = ss.str();
            copy (begin, end, ostream_iterator <std::string> (cout, s.c_str()));
        }
};

int main()
{
    list <string> l;
    l.push_back ("Hello");
    l.push_back ("world");

    Gizmo <unsigned> g (42);
    g.DoIt (l, l.begin(), l.end());
}

看它跑到这里来。

票数 2
EN

Stack Overflow用户

发布于 2014-02-03 19:05:42

我好像没抓住重点,但你为什么不能这么做呢?

代码语言:javascript
复制
template <typename Iterator> void DoIt(
    Iterator begin,
    Iterator end)
    {
      // snip
    }

// [...]

list <string> l;
l.push_back ("Hello");
l.push_back ("world");
vector <string> v;
v.push_back ("Hello");
v.push_back ("world");

Gizmo <unsigned> g (42);
g.DoIt (l.begin(), l.end());
g.DoIt (v.begin(), v.end());
票数 1
EN

Stack Overflow用户

发布于 2014-02-04 05:42:43

我认为您实际上并不关心您的输入是vector,还是list,甚至是容器。我认为您真正关心的是,您有一系列可以迭代的东西,可以转换为string。因此,您应该接受其value_type is_convertible to string (在Coliru现场演示)的任何迭代器:

代码语言:javascript
复制
template <typename Iter>
typename enable_if<
  is_convertible<
    typename iterator_traits<Iter>::value_type,string
  >::value
>::type DoIt(Iter begin, Iter end) const
{
    stringstream ss;
    ss << "(" << this->mF << ")\n";
    const std::string s = ss.str();
    copy (begin, end, ostream_iterator <std::string> (cout, s.c_str()));
}

我对约束的丑陋表示歉意,概念Lite不能很快到达这里。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/21534181

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档