如何创建可以使用不同类型参数处理std::set的模板类 我需要在C++中编写一个模板来实现一个集合的抽象版本。我找不到解决编译错误的方法(更糟的是,我真的不知道该怎么办)

如何创建可以使用不同类型参数处理std::set的模板类 我需要在C++中编写一个模板来实现一个集合的抽象版本。我找不到解决编译错误的方法(更糟的是,我真的不知道该怎么办),c++,class,templates,set,C++,Class,Templates,Set,这是我需要编译和运行的主程序的简化版本——也就是说,我不能更改以下内容: #include <algorithm> #include <iostream> #include <iterator> #include <numeric> #include <set> #include <string> #include "testset.h" using namespace std; struct string_size_l

这是我需要编译和运行的主程序的简化版本——也就是说,我不能更改以下内容:

#include <algorithm>
#include <iostream>
#include <iterator>
#include <numeric>
#include <set>
#include <string>
#include "testset.h"

using namespace std;

struct string_size_less
{

  bool operator()( const std::string& a,
                   const std::string& b )
  {
    return a.size() < b.size();
  }

};

int main()
{
    std::set<std::string> msgs;
    msgs.insert("One");
    msgs.insert("Two");
    msgs.insert("Three");

    set_ops<std::string> ops(msgs);
    ops.list();

    std::set<std::string, string_size_less> x;
    x.insert("Hello");
    x.insert("Ciao");

    std::set<std::string, std::greater<std::string> > a;
    a.insert(":-o");

    set_ops<std::string> m(x);
    m.list();

    return 0;
}

#包括
#包括
#包括
#包括
#包括
#包括
#包括“testset.h”
使用名称空间std;
结构字符串大小小于
{
布尔运算符()(常量std::string&a,
const std::string(字符串和b)
{
返回a.size()
我需要编写“set_ops”类(在testset.h中)。我剥离了所有不相关的部分(否则会起作用):

#pragma一次
#包括
#包括
使用名称空间std;
模板类集合
{
私人:
std::集合元素;
公众:
集合操作(标准::集合初始集合)
{
元素=初始集;
}
无效列表()常量;
};
模板无效集_ops::list()常量
{
for(typename set::iterator i=elements.begin();i!=elements.end();++i){

这可以通过多态性和模板构造函数来实现

#include <utility>
#include <memory>
#include <iostream>

template <typename T>
class set_ops
{
private:
    // Interface type.
    class set_ops_iface
    {
    public:
        virtual ~set_ops_iface();

        virtual void list() const = 0;
    };

    // Concrete implementation for a U.
    template <typename U>
    class set_ops_impl : public set_ops_iface
    {
    private:
        U value;

    public:
        explicit set_ops_impl(U);

        virtual void list() const override;
    };

private:
    // Smart pointer to interface type.
    std::unique_ptr<set_ops_iface> impl;

public:
    // Template constructor that can take any kind of container (not just sets)
    template <typename U>
    set_ops(U);

    void list() const;
};

// Template constructor creates a set_ops_impl<U> owned by the interface smart pointer.
template <typename T>
template <typename U>
set_ops<T>::set_ops(U initial) :
    impl{std::make_unique<set_ops_impl<U>>(std::move(initial))} { }

template <typename T>
set_ops<T>::set_ops_iface::~set_ops_iface() { }

template <typename T>
template <typename U>
set_ops<T>::set_ops_impl<U>::set_ops_impl(U initial) :
    value{std::move(initial)} { }

// real list() implementation is in set_ops_impl<U>
template <typename T>
template <typename U>
void set_ops<T>::set_ops_impl<U>::list() const {
    for (auto const & i : value) {
        std::cout << '\t' << i << '\n';
    }
}

// set_ops::list proxies to the polymorphic implementation.
template <typename T>
void set_ops<T>::list() const {
    impl->list();
}
#包括
#包括
#包括
模板
类集合运算
{
私人:
//接口类型。
类集_ops _iface
{
公众:
虚拟~set_ops_iface();
虚空列表()常量=0;
};
//具体执行一项联合国决议。
模板
类集合操作简易:公共集合操作简易
{
私人:
U值;
公众:
显式集合运算显式(U);
虚空列表()常量覆盖;
};
私人:
//指向接口类型的智能指针。
std::唯一的\u ptr impl;
公众:
//可以接受任何类型容器(而不仅仅是集合)的模板构造函数
模板
设置操作(U);
无效列表()常量;
};
//模板构造函数创建由接口智能指针拥有的集合操作impl。
模板
模板
设置操作::设置操作(U首字母):
impl{std::make_unique(std::move(initial))}{
模板
set_ops::set_ops_iface::~set_ops_iface(){}
模板
模板
集合运算::集合运算执行::集合运算执行(U首字母):
值{std::move(初始)}{}
//real list()实现在set_ops_impl中
模板
模板
void set_ops::set_ops_impl::list()常量{
用于(自动常量和i:值){

这可以通过多态性和模板构造函数来实现

#include <utility>
#include <memory>
#include <iostream>

template <typename T>
class set_ops
{
private:
    // Interface type.
    class set_ops_iface
    {
    public:
        virtual ~set_ops_iface();

        virtual void list() const = 0;
    };

    // Concrete implementation for a U.
    template <typename U>
    class set_ops_impl : public set_ops_iface
    {
    private:
        U value;

    public:
        explicit set_ops_impl(U);

        virtual void list() const override;
    };

private:
    // Smart pointer to interface type.
    std::unique_ptr<set_ops_iface> impl;

public:
    // Template constructor that can take any kind of container (not just sets)
    template <typename U>
    set_ops(U);

    void list() const;
};

// Template constructor creates a set_ops_impl<U> owned by the interface smart pointer.
template <typename T>
template <typename U>
set_ops<T>::set_ops(U initial) :
    impl{std::make_unique<set_ops_impl<U>>(std::move(initial))} { }

template <typename T>
set_ops<T>::set_ops_iface::~set_ops_iface() { }

template <typename T>
template <typename U>
set_ops<T>::set_ops_impl<U>::set_ops_impl(U initial) :
    value{std::move(initial)} { }

// real list() implementation is in set_ops_impl<U>
template <typename T>
template <typename U>
void set_ops<T>::set_ops_impl<U>::list() const {
    for (auto const & i : value) {
        std::cout << '\t' << i << '\n';
    }
}

// set_ops::list proxies to the polymorphic implementation.
template <typename T>
void set_ops<T>::list() const {
    impl->list();
}
#包括
#包括
#包括
模板
类集合运算
{
私人:
//接口类型。
类集_ops _iface
{
公众:
虚拟~set_ops_iface();
虚空列表()常量=0;
};
//具体执行一项联合国决议。
模板
类集合操作简易:公共集合操作简易
{
私人:
U值;
公众:
显式集合运算显式(U);
虚空列表()常量覆盖;
};
私人:
//指向接口类型的智能指针。
std::唯一的\u ptr impl;
公众:
//可以接受任何类型容器(而不仅仅是集合)的模板构造函数
模板
设置操作(U);
无效列表()常量;
};
//模板构造函数创建由接口智能指针拥有的集合操作impl。
模板
模板
设置操作::设置操作(U首字母):
impl{std::make_unique(std::move(initial))}{
模板
set_ops::set_ops_iface::~set_ops_iface(){}
模板
模板
集合运算::集合运算执行::集合运算执行(U首字母):
值{std::move(初始)}{}
//real list()实现在set_ops_impl中
模板
模板
void set_ops::set_ops_impl::list()常量{
用于(自动常量和i:值){

std::cout另一个答案之所以有效,是因为
std::function
使用了一种称为“类型擦除”的技术。如果您不想保留多个
std::functions
,您可以自己实现类型擦除

template<typename T>
struct set_ops_erased {
    virtual ~set_ops_erased() = default;
    virtual void list() = 0;
};

template<typename T, typename Comp>
struct set_ops_impl : set_ops_erased<T> {
    std::set<T, Comp> s;
    set_ops_impl(std::set<T, Comp> s) : s(std::move(s)) { }
    void list() override {
        for(auto &x : s) std::cout << "\t" << x << "\n"; // endl is normally not necessary
    }
};

template<typename T>
class set_ops {
     std::unique_ptr<set_ops_erased<T>> ops;
public:
     template<typename Comp>
     set_ops(std::set<T, Comp> s)
     : ops(std::make_unique<set_ops_impl<T, Comp>>(std::move(s)))
     { }

     void list() { ops->list(); }
};
模板
结构集\u操作\u已删除{
virtual~set_ops_erased()=默认值;
虚空列表()=0;
};
模板
结构集合操作执行:集合操作已擦除{
std::集s;
set_ops_impl(std::set s):s(std::move(s)){
无效列表()覆盖{

对于(auto&x:s)std::cout另一个答案有效,因为
std::function
使用了一种称为“类型擦除”的技术。如果您不想保留多个
std::functions
,您可以自己实现类型擦除

template<typename T>
struct set_ops_erased {
    virtual ~set_ops_erased() = default;
    virtual void list() = 0;
};

template<typename T, typename Comp>
struct set_ops_impl : set_ops_erased<T> {
    std::set<T, Comp> s;
    set_ops_impl(std::set<T, Comp> s) : s(std::move(s)) { }
    void list() override {
        for(auto &x : s) std::cout << "\t" << x << "\n"; // endl is normally not necessary
    }
};

template<typename T>
class set_ops {
     std::unique_ptr<set_ops_erased<T>> ops;
public:
     template<typename Comp>
     set_ops(std::set<T, Comp> s)
     : ops(std::make_unique<set_ops_impl<T, Comp>>(std::move(s)))
     { }

     void list() { ops->list(); }
};
模板
结构集\u操作\u已删除{
virtual~set_ops_erased()=默认值;
虚空列表()=0;
};
模板
结构集合操作执行:集合操作已擦除{
std::集s;
set_ops_impl(std::set s):s(std::move(s)){
无效列表()覆盖{

对于(auto&x:s)std::cout,不更改主文件,但忘记给定集合的初始顺序(因为您没有指定预期输出),您可以执行以下操作:

template <class T> class set_ops
{
private:
    std::set<T> elements;

public:
    template <typename Container>
    set_ops(Container& c) : elements(c.begin(), c.end()) {}

    void list() const {
        for (const auto& e : elements) {
            std::cout << "\t" << e << std::endl;
        }  
    }
};

模板类集合
{
私人:
std::集合元素;
公众:
模板
集合操作(容器&c):元素(c.begin(),c.end()){}
无效列表()常量{
用于(常量自动和e:元素){

std::cout不更改主文件,但忘记给定集合的初始顺序(因为您没有指定预期输出),您可以执行以下操作:

template <class T> class set_ops
{
private:
    std::set<T> elements;

public:
    template <typename Container>
    set_ops(Container& c) : elements(c.begin(), c.end()) {}

    void list() const {
        for (const auto& e : elements) {
            std::cout << "\t" << e << std::endl;
        }  
    }
};

模板类集合
{
私人:
std::集合元素;
公众:
模板
集合操作(容器&c):元素(c.begin(),c.end()){}
无效列表()常量{
用于(常量自动和e:元素){

std::cout AFAIK如果不更改
main
@NathanOliver,则无法执行此操作。滥用多态性确实可以。是否指定了输出?否则您可以复制内容并更改顺序。AFAIK如果不更改
main
@NathanOliver,则无法执行此操作确实可以滥用多态性
template <class T> class set_ops
{
private:
    std::set<T> elements;

public:
    template <typename Container>
    set_ops(Container& c) : elements(c.begin(), c.end()) {}

    void list() const {
        for (const auto& e : elements) {
            std::cout << "\t" << e << std::endl;
        }  
    }
};