Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 如何在虚拟方法上使用模板参数类?_C++_Oop_Templates_C++11 - Fatal编程技术网

C++ 如何在虚拟方法上使用模板参数类?

C++ 如何在虚拟方法上使用模板参数类?,c++,oop,templates,c++11,C++,Oop,Templates,C++11,我知道在虚拟方法上使用模板是不可能的,因为编译无法知道如何实现所有可能性,但我需要的是以受限的方式使用模板,如: template<typename T, size_t N> class MatBase { public: static constexpr size_t order = N; using value_type = T; MatBase() = default; virtual ~MatBase() = default; template&l

我知道在虚拟方法上使用模板是不可能的,因为编译无法知道如何实现所有可能性,但我需要的是以受限的方式使用模板,如:

template<typename T, size_t N>
class MatBase {
 public:
  static constexpr size_t order = N;

  using value_type = T;

  MatBase() = default;
  virtual ~MatBase() = default;

  template<class Fn = T(T)>
  virtual void Map(Fn&& fn) = 0;

  template<class Fn = T(T,T)>
  virtual T Reduce(Fn&& fn) = 0;
};
模板
类MatBase{
公众:
静态constexpr size\u t order=N;
使用值_type=T;
MatBase()=默认值;
virtual~MatBase()=默认值;
模板
虚空图(Fn&&Fn)=0;
模板
虚拟T减少(Fn&&Fn)=0;
};

这意味着,Fn使用类上声明的模板,所以我认为编译器可以推断出所有可能的类型。有没有办法做到像C++那样?

正如你所说的,你不能有模板化的虚拟函数。但是,为什么您需要模板呢?请参见下面的示例代码

示例代码
#包括
模板
类MatBase
{
公众:
静态constexpr size\u t order=N;
使用MapFn=T(*)(T);
使用ReduceFn=T(*)(T,T);
使用值_type=T;
MatBase()=默认值;
virtual~MatBase()=默认值;
虚空映射(MapFn&&fn){}
虚T Reduce(ReduceFn&&fn){}
};
int main()
{
基质m;
返回0;
}



一个更灵活的解决方案可以考虑使用<代码> STD::函数< /COD>(例如,<代码> STD::函数< /代码>)用于参数,因为它给调用方更多的灵活性。例如,调用方可以使用普通函数、成员函数、lambda表达式或functor对象。

如您所述,不能使用模板虚拟函数。但是,为什么您需要模板呢?请参见下面的示例代码

示例代码
#包括
模板
类MatBase
{
公众:
静态constexpr size\u t order=N;
使用MapFn=T(*)(T);
使用ReduceFn=T(*)(T,T);
使用值_type=T;
MatBase()=默认值;
virtual~MatBase()=默认值;
虚空映射(MapFn&&fn){}
虚T Reduce(ReduceFn&&fn){}
};
int main()
{
基质m;
返回0;
}



一个更灵活的解决方案可以考虑使用<代码> STD::函数< /COD>(例如,<代码> STD::函数< /代码>)用于参数,因为它给调用方更多的灵活性。例如,调用者可以使用普通函数、成员函数、lambda表达式或functor对象。

另一个答案将适用于普通函数指针。但是,使用一点类型擦除,或者对其进行一些修改,也可以使实现合适的
操作符()
成员的类的实例实现这种功能

我将为
Map()
写出这篇文章。对
Reduce()
重复相同的方法类似,这将是一项家庭作业:

#include <cstddef>

template<typename T, size_t N>
class MatBase
{
public:
    static constexpr size_t order = N;

    using value_type = T;

    MatBase() = default;
    virtual ~MatBase() = default;

    template<typename Arg> void Map(Arg && arg)
    {
        std::function< value_type(value_type> > f=
               [&]
               (value_type value)
               {
                   return arg(value);
               };

        do_map(f);
     }

     virtual void do_map(std::function< value_type(value_type) > &)=0;
};
#包括
模板
类MatBase
{
公众:
静态constexpr size\u t order=N;
使用值_type=T;
MatBase()=默认值;
virtual~MatBase()=默认值;
模板无效映射(Arg&&Arg)
{
标准::函数<值类型>(值类型>>f=
[&]
(值\类型值)
{
返回arg(值);
};
dou图(f);
}
虚空do_映射(std::function&)=0;
};

另一个答案将适用于普通的、花园式的函数指针。但是使用一点类型擦除,或者对其进行一些修改,也可以使这一方法适用于实现合适的
操作符()成员的类实例

我将为
Map()
写下这篇文章。对
Reduce()
重复同样的方法也是类似的,这将是一个家庭作业:

#include <cstddef>

template<typename T, size_t N>
class MatBase
{
public:
    static constexpr size_t order = N;

    using value_type = T;

    MatBase() = default;
    virtual ~MatBase() = default;

    template<typename Arg> void Map(Arg && arg)
    {
        std::function< value_type(value_type> > f=
               [&]
               (value_type value)
               {
                   return arg(value);
               };

        do_map(f);
     }

     virtual void do_map(std::function< value_type(value_type) > &)=0;
};
#包括
模板
类MatBase
{
公众:
静态constexpr size\u t order=N;
使用值_type=T;
MatBase()=默认值;
virtual~MatBase()=默认值;
模板无效映射(Arg&&Arg)
{
标准::函数<值类型>(值类型>>f=
[&]
(值\类型值)
{
返回arg(值);
};
dou图(f);
}
虚空do_映射(std::function&)=0;
};

为什么你不能只写
虚拟空位映射(t(&&&)(t))=0;
?t(&&&)(t)和t(*)(t)之间有什么区别?一个是右值引用,一个是指针。我更喜欢@James的版本。为什么你不能只写
虚拟空位映射(t(&&&)(t))=0;
?t(&&&&)(t)和t(*)(t)之间有什么区别一个是右值引用,一个是指针。TBH我更喜欢@James的版本。最好使用
使用MapFn=T(&&&)(T);
并调用virtualvoid
Map(MapFn-fn)=0;
?@Alex我不确定您为什么要使用
&
,所以我保留了它们。如果您使用的是普通函数指针,那么我可能会使用
虚拟空映射(MapFn-fn)=0;
@Alex注意,您可能希望接受
std::function
作为参数类型,因为它更灵活(即,调用方可以使用普通函数、lambda表达式、成员函数)。事实上,此函数将传递给CUDA,因此我在使用std::function时遇到问题,我需要通过复制或移动将其作为模板参数传递。最好使用
使用MapFn=T(&&&)(T);
并调用virtual void
Map(MapFn-fn)=0;
?@Alex我不确定您为什么要使用
&
,所以我保留了它们。如果您使用的是普通函数指针,那么我可能会使用
虚拟空映射(MapFn-fn)=0;
@Alex注意,您可能希望接受
std::function
作为参数类型,因为它更灵活(即调用方可以使用普通函数、lambda表达式、成员函数)。事实上,此函数将传递给CUDA,因此我在使用std::function时遇到问题,我需要通过复制或移动将其作为模板参数传递。