接受函数模板实参的类模板,这些实参对正在定义的类的实例进行操作

class template that takes function template arguments that operate on an instance of the class being defining

本文关键字:实参 定义 实例 操作 函数模板      更新时间:2023-10-16

我想定义一个类模板,它接受函数模板参数,这些参数在正在定义的类的实例上操作。

这或类似的东西是可能的吗?

我知道我可以定义转换构造函数,但是由于这个简化示例中没有明确的原因,我希望能够在不更改其定义或创建派生类型的情况下改变类的功能。

我知道我可以包括函数指针成员并使用setter来修复它们的功能,但我更愿意使用声明式类型定义来修复类的功能,而不是通过编程来修复。

template 
    < typename T
    , MyClass<X> (to_X)(MyClass<T>)
    , MyClass<T> (from_X)(MyClass<X>)
    >
class MyClass {
    T value;
    MyClass(T v) : value(v) {}
    // is it possible to use to_X and from_X template args 
            // to declare member functions ...
}
MyClass<int> to_int(MyClass<std::string> value ) {
    // return result of conversion
}
MyClass<std::string> to_string(MyClass<int> value ) {
    // return result of conversion
}
MyClass<std::string, to_string, to_int> foo1 = 
        MyClass<std::string, to_string, to_int>("5");
MyClass<int, to_int, to_string> * foo2 = foo1.to_int();

我建议您使用策略-类方法:您的类模板使用两个转换策略参数化

template<typename T,
         typename FROM,
         typename TO
        >
class MyClass
{
    FROM from_t_conversion;
    TO   to_t_conversion;
    MyClass() = default;
    template<typename U>
    operator U() const
    {
        return from_t_conversion( *this );
    }
    template<typename U>
    MyClass( const U& u ) : MyClass()
    {
        std::swap( *this , to_t_conversion( u ) );
    }
};

此设计的重点是转换策略的类型(形式):转换策略可以是任何具有预期签名的可调用实体:函数、函子、lambda等。

EDIT:下面是一个转换器的例子:

struct float_to_int
{
    MyClass<itn> operator()( const MyClass<float>& )
    {
        return MyClass<int>{};
    }
};
//A more generic conversion function:
template<typename T>
struct generic_to_converter
{
    template<typename U , typename X = T>
    MyClass<X> operator()( const MyCLass<U>& )
    {
        return /* something /*
    }
};

也许不要想太多,保持简单:

template <typename T, typename Converter>
class MyClass
{
    T value;
    Converter converter;
public:
    explicit MyClass(T const & v, Converter const & c = Converter())
    : value(v), converter(c)
    { }
    template <typename U, typename C = Converter>
    operator MyClass<U, C>() const
    {
        return converter.template convert<U, C>(*this);
    }
};

您的转换器需要看起来像这样:

struct ExampleConverter
{
    template <typename U, typename C1, typename T, typename C2>
    MyClass<U, C1> convert(MyClass<T, C2> const &) const;
};

稍加努力,您就可以利用基类布局优化(与标准库实现通常考虑分配器和比较器的方式相同)。


你也可以有一些重新绑定机制,允许转换器本身成为一个模板。

template <typename T, typename Converter = StandardConverter<T>>
class MyClass
{
    T value;
    Converter converter;
public:
    explicit MyClass(T const & v, Converter const & c = Converter())
    : value(v), converter(c)
    { }
    template <typename U,
              typename C = typename Converter::template rebind<U>::type>
    operator MyClass<U, C>() const
    {
        return converter.template convert<U, C>(*this);
    }
};
template <typename T>
struct StandardConverter
{
    template <typename U, typename C>
    MyClass<U, C> convert(MyClass<T, StandardConverter<T>> const &) const;
    template <typename U> struct rebind { using type = StandardConverter<U>; };
};