Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/156.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++;试图创建一个';中级';函子_C++_Callback_Functor_Variadic Templates - Fatal编程技术网

C++ C++;试图创建一个';中级';函子

C++ C++;试图创建一个';中级';函子,c++,callback,functor,variadic-templates,C++,Callback,Functor,Variadic Templates,我所说的“中间”函子是指:一个普通函子,其中一个参数可以在调用时指定。问题是我有一个动画时间轴(基本上是特定帧上的标量值),它的输出需要通过管道传输到要设置动画的对象中的getter/setter方法。下面是我尝试的一个简化示例: template < class ObjType, class Getter, class Setter, typename Scalar > class Sy_propertyBridge : public Sy_abstractPropertyBrid

我所说的“中间”函子是指:一个普通函子,其中一个参数可以在调用时指定。问题是我有一个动画时间轴(基本上是特定帧上的标量值),它的输出需要通过管道传输到要设置动画的对象中的getter/setter方法。下面是我尝试的一个简化示例:

template < class ObjType, class Getter, class Setter, typename Scalar >
class Sy_propertyBridge : public Sy_abstractPropertyBridge
{
public:
                        Sy_propertyBridge( ObjType* object, Getter getter,
                                           Setter setter )
                            : obj_( object ), get_( getter ),
                              set_( setter ) {}
    virtual            ~Sy_propertyBridge() {}

    inline virtual float get() const
                        {
                            //  Cannot handle default arguments.
                            Scalar tmp = ( obj_->*get_ )();
                            return static_cast< float >( tmp );
                        }
    inline virtual void set( float value )
                        {
                            Scalar tmp = static_cast< Scalar >( value );
                            ( obj_->*set_ )( tmp );
                        }
private:
    ObjType*            obj_;
    Getter              get_;
    Setter              set_;
};
template
类Sy_propertyBridge:公共Sy_abstractPropertyBridge
{
公众:
Sy_propertyBridge(对象类型*对象,Getter-Getter,
设定器(设定器)
:obj_(对象),get_(getter),
集合{(集合器){}
虚拟~Sy_propertyBridge(){}
内联虚拟浮点get()常量
{
//无法处理默认参数。
标量tmp=(obj \->*get \)();
返回静态_cast(tmp);
}
内联虚拟空集(浮点值)
{
标量tmp=静态施法<标量>(值);
(obj->*集合(tmp);
}
私人:
对象类型*对象类型;
Getter-get;
设定器设定;
};
时间轴只保存浮点数,因此无论对象用于其getter/setter方法的标量类型是什么,都必须强制转换(我对浮点数进行了部分专门化,从而消除了强制转换)
ObjType
是动画对象类型,
Getter
Setter
是指向方法的指针,
Scalar
是期望处理的Getter和Setter类型

我认为这很好,但编译失败了,因为一些getter/setter还有其他默认的初始化参数。我不认为这会是一个问题,因为他们是默认的!但是,当编译器预期指向方法的指针的参数比我提供的要多时,它失败了

然后,我尝试使用可变模板参数,以便可以手动输入默认值,但在第一个障碍时失败了,因为我无法将参数包存储为成员,以作为参数重复应用于方法指针。我还研究了std::function和std::bind,我希望能够使用getter/setter方法的默认参数预设将std::function存储为成员,并在调用之前从时间线中更改相应的参数。只是我找不到办法


有没有人对实现我的目标有什么建议?或者我的设计根本上有缺陷,有更简单的方法吗?

据我所知,您试图使用“get”和“set”方法,这两种方法在这里传递的每个类中都有所不同?如果是这样,我认为您应该尝试在“ObjType”对象上使用纯虚拟基类,然后在您传递的类中实现它。在C#/Java术语中,一种接口

基本上:

class IGetSetter
{
    virtual float get() const = 0;
    virtual void set(float) = 0;    
}

class ObjType1 : public IGetSetter
{
    virtual float get() const
    {
        // Implementation
    }

    virtual void set(float a)
    {
        // Implementation
    }
}

class ObjType2 : public IGetSetter
{
    virtual float get() const
    {
        // Implementation
    }

    virtual void set(float a)
    {
        // Implementation
    }
}
然后你的班级变成:

template < typename Scalar >
class Sy_propertyBridge : public Sy_abstractPropertyBridge
{
public:
    Sy_propertyBridge( IGetSetter* object)
        : obj_( object ) {}
    virtual ~Sy_propertyBridge() {}

    inline virtual float get() const
    {
        Scalar tmp = obj_->get();  // Uses polymorphism to find the right method
        return static_cast< float >( tmp );
    }
                        }
    inline virtual void set( float value )
    {
        Scalar tmp = static_cast< Scalar >( value );
        obj_->set( tmp );  // Uses polymorphism to find the right method
    }
private:
    ObjType* obj_;
};
模板
类Sy_propertyBridge:公共Sy_abstractPropertyBridge
{
公众:
Sy_propertyBridge(IGetSetter*对象)
:obj_(object){}
虚拟~Sy_propertyBridge(){}
内联虚拟浮点get()常量
{
Scalar tmp=obj->get();//使用多态性找到正确的方法
返回静态_cast(tmp);
}
}
内联虚拟空集(浮点值)
{
标量tmp=静态施法<标量>(值);
obj->set(tmp);//使用多态性找到正确的方法
}
私人:
对象类型*对象类型;
};

但实际上,有一种简单的方法可以完全取消Sy_propertyBridge类。只要存储一个指向
IGetSetter
的指针数组,然后直接调用它们(如果它们执行您想要的操作)。

据我所知,您正在尝试使用“get”和“set”方法,这些方法随您在此处传递的类而异?如果是这样,我认为您应该尝试在“ObjType”对象上使用纯虚拟基类,然后在您传递的类中实现它。在C#/Java术语中,一种接口

基本上:

class IGetSetter
{
    virtual float get() const = 0;
    virtual void set(float) = 0;    
}

class ObjType1 : public IGetSetter
{
    virtual float get() const
    {
        // Implementation
    }

    virtual void set(float a)
    {
        // Implementation
    }
}

class ObjType2 : public IGetSetter
{
    virtual float get() const
    {
        // Implementation
    }

    virtual void set(float a)
    {
        // Implementation
    }
}
然后你的班级变成:

template < typename Scalar >
class Sy_propertyBridge : public Sy_abstractPropertyBridge
{
public:
    Sy_propertyBridge( IGetSetter* object)
        : obj_( object ) {}
    virtual ~Sy_propertyBridge() {}

    inline virtual float get() const
    {
        Scalar tmp = obj_->get();  // Uses polymorphism to find the right method
        return static_cast< float >( tmp );
    }
                        }
    inline virtual void set( float value )
    {
        Scalar tmp = static_cast< Scalar >( value );
        obj_->set( tmp );  // Uses polymorphism to find the right method
    }
private:
    ObjType* obj_;
};
模板
类Sy_propertyBridge:公共Sy_abstractPropertyBridge
{
公众:
Sy_propertyBridge(IGetSetter*对象)
:obj_(object){}
虚拟~Sy_propertyBridge(){}
内联虚拟浮点get()常量
{
Scalar tmp=obj->get();//使用多态性找到正确的方法
返回静态_cast(tmp);
}
}
内联虚拟空集(浮点值)
{
标量tmp=静态施法<标量>(值);
obj->set(tmp);//使用多态性找到正确的方法
}
私人:
对象类型*对象类型;
};

但实际上,有一种简单的方法可以完全取消Sy_propertyBridge类。只要存储一个指向IGetSetter的指针数组,然后直接调用它们(如果它们执行您想要的操作)。

std::function
就是一种方法。将只使用
std::function
作为getter,
std::function
作为setter(如果
Scalar
s隐式转换为/从
float
s,我甚至会分别使用
std::function
std::function
)。您可以使用lambda函数初始化这些函数:

Sy_propertyBridge(my_obj, 
  [](const MyObjType* o) -> float { return o->opacity; }, 
  [](const MyObjType* o, float f) { o->opacity=f; })
请注意,可能有更优雅的方法来实现这一点(例如,可能只有一个函数可以同时用作getter和setter)

更进一步说,你可以

  • 去掉
    obj
    成员变量
  • o
    参数去掉以