首页 > 解决方案 > C++ - 模板类中带有模板参数的模板静态方法

问题描述

我有这两个类:

template <typename GeomType>
class InputCSV
{
public:
    InputCSV(DataSet<GeomType> * ds) : ds(ds) {}
    virtual ~InputLoaderCSV() = default;

    DataSet<GeomType> * ds;
};

template <typename GeomType>
struct DataSet
{
    template <typename LoaderType>
    static DataSet<GeomType> Create()
    {
        DataSet<GeomType> ds;
        ds.fileName = "something";
        ds.input = std::make_shared<LoaderType<GeomType>>(&ds);
        return std::move(ds);
    };

    DataSet(const DataSet & ds) = delete;

    DataSet(DataSet && ds)
    {
        this->fileName = std::move(ds.fileName);
        this->input = std::move(ds.input);
        this->input->ds = this;

        ds.input = nullptr;     
    }

    std::string fileName;
    std::shared_ptr<InputLoader<GeomType>> input;

   protected:   
        DataSet() : input(nullptr) {}
}

现在在代码的某个地方,我想做

auto ds = DataSet<Line>::Create<InputCSV>();

其中 Line 是我拥有的一些结构。但是,这不起作用,我收到此错误:

error C2672: 'DataSet<Line>::Create': no matching overloaded function found
error C3206: 'DataSet<Line>::Create': invalid template argument for 'LoaderType', missing template argument list on class template 'InputLoaderCSV'
note: see declaration of 'DataSet<Line>::Create' 
error cannot access protected member declared in class 'DataSet<Line>'
note: see declaration of 'DataSet<Line>::DataSet' note: see declaration of 'DataSet<Line>'

有这种“语法”的解决方案吗,或者我必须写

auto ds = DataSet<Line>::Create<InputCSV<Line>>();

和改变

ds.input = std::make_shared<LoaderType<GeomType>>(&ds);

ds.input = std::make_shared<LoaderType>(&ds);

在这个例子中,我不喜欢 InputCSV 中的“重复”,因为不可能有其他任何东西。

标签: c++templates

解决方案


您正在寻找的是一个模板模板参数。由于InputCSV是模板类型,因此您必须指定其模板参数。如果您Create改为使用模板模板参数,那么您可以将模板传递给Create并像使用任何其他模板一样使用它。为此,您需要使用

template <template<typename> typename LoaderType>
// pre C++17 you have to use template <template<class> class LoaderType> instead
static DataSet<GeomType> Create()
{
    DataSet<GeomType> ds;
    ds.fileName = "something";
    ds.input = std::make_shared<LoaderType<GeomType>>(&ds);
    return std::move(ds);
}

然后你保持使用

auto ds = DataSet<Line>::Create<InputCSV>();

nowLoaderType是一个模板类型,它接受一个模板参数,您可以在函数内部指定该参数。


推荐阅读