c++ - 用 C++ 编写类型类

标签 c++ templates metaprogramming typeclass template-meta-programming

我正在尝试用 C++ 为一组类型类编写类似的东西,我正在努力解决如何安排模板签名,或者是否有可能做我想做的事情。

把它分解成最小的例子,假设我有这个:

template<typename S, typename T>
struct Homomorphism {
    //Defined in specialization: static const T morph(const S&);
    static constexpr bool is_instance = false;
    using src  = S;
    using dest = T;
};

template<typename S, typename T>
struct Monomorphism : Homomorphism<S, T> {
    //Defined in specialization: static const T morph(const &S);
    static constexpr bool is_instance = false;
    using src  = S;
    using dest = T;
};

我在我的程序中针对数据类型对这些类(和其他态射)进行了特化。

我现在想做的是编写一个结构模板,它将采用两个同态或两个单态,并将它们组合起来分别生成一个新的同态或单态结构,即类似于:

template<typename S, typename T, typename U,
         typename HST = Homomorphism<S, T>,
         typename HTU = Homomorphism<T, U>,
         typename HSU = Homomorphism<S, U> >
struct CompositionMorphism : HSU {
    static const U morph(const S &s) {
        return HTU::morph(HST::morph(s));
    }
    static constexpr bool is_instance = true;
    using src  = S;
    using dest = U;
}

这实际上适用于通过以下方式组合特殊的同态实例:

CompositionMorphism<Class1, Class2, Class3>::morph(class1Instance);

当我有:

struct Homomorphism<Class1, Class2> {
    static const Class2 morph(const Class1 &c) {
        ...
    }
};

Homomorphism<Class2, Class3> 类似.

但是,现在我想写:

template<typename S, typename T, typename U,
        typename MST = Monomorphism<S, T>,
        typename MTU = Monomorphism<T, U>,
        typename MSU = Monomorphism<S, U> >
struct CompositionMorphism : MSU {
    static const U morph(const S &s) {
        return MTU::morph(MST::morph(s));
    }
    static constexpr bool is_instance = true;
    using src  = S;
    using dest = U;
};

但是编译器毫不奇怪地提示 CompositionMorphism 的重复定义。 .

有没有办法写CompositionMorphism及其专业 HomomorphismMonomorphism这样我就可以做一些事情,比如打电话:

template<> struct Homomorphism<Class1, Class2> { ... };
template<> struct Homomorphism<Class2, Class3> { ... };
CompositionMorphism<Class1, Class2, Class3>::morph(c1Instance);

或:

template<> struct Monomorphism<Class1, Class2> { ... };
template<> struct Monomorphism<Class2, Class3> { ... };
CompositionMorphism<Class1, Class2, Class3>::morph(c1Instance);

或:

template<> struct Monomorphism<Class1, Class2> { ... };
template<> struct Homomorphism<Class2, Class3> { ... };
CompositionMorphism<Class1, Class2, Class3>::morph(c1Instance);

并让编译器选择最接近的 CompositionMorphism基于我的态射层次结构的特化?

最佳答案

你可以尝试写一个模板来选择HomomorphismMonomorphism基于 SFINAE 上的 morph功能。

template <typename S, typename T, typename = void>
struct SelectMorphism {
    using type = Homomorphism<S, T>;
};

template <typename S, typename T>
struct SelectMorphism<S, T, std::enable_if_t<std::is_same_v<decltype(Monomorphism<S, T>::morph(std::declval<S>())), const T>>> {
    using type = Monomorphism<S, T>;
};

这将检查是否 Monomorphism<S, T>::morph(S)会返回 T ,如果是,请选择 Monomorphism<S, T> .如果不是,SFINAE 将失败并默认为 Homomorphism<S, T> .

然后我们改变CompositionMorphism像这样使用这个模板

template<typename S, typename T, typename U,
         typename HST = typename SelectMorphism<S, T>::type,
         typename HTU = typename SelectMorphism<T, U>::type,
         typename HSU = typename SelectMorphism<S, U>::type >
struct CompositionMorphism : HSU {
    static const U morph(const S &s) {
        return HTU::morph(HST::morph(s));
    }
    static constexpr bool is_instance = true;
    using src  = S;
    using dest = U;
};

你可以看到一个live demo here这个完整的工作示例。它需要 c++17但可以写成 c++11以及(稍微更冗长)。

#include <iostream>

template<typename S, typename T>
struct Homomorphism {
    //Defined in specialization: static const T morph(const S&);
    static constexpr bool is_instance = false;
    using src  = S;
    using dest = T;
};

template<typename S, typename T>
struct Monomorphism : Homomorphism<S, T> {
    //Defined in specialization: static const T morph(const &S);
    static constexpr bool is_instance = false;
    using src  = S;
    using dest = T;
};

template <typename S, typename T, typename = void>
struct SelectMorphism {
    using type = Homomorphism<S, T>;
};

template <typename S, typename T>
struct SelectMorphism<S, T, std::enable_if_t<std::is_same_v<decltype(Monomorphism<S, T>::morph(std::declval<S>())), const T>>> {
    using type = Monomorphism<S, T>;
};

struct Class1 {};

struct Class2 {};

struct Class3 {};

template<>
struct Monomorphism<Class1, Class2> : Homomorphism<Class1, Class2> {
    static const Class2 morph(const Class1&) { std::cout << "Morphing in Mono<Class1, Class2>" << std::endl; return Class2{}; }
    static constexpr bool is_instance = false;
    using src  = Class1;
    using dest = Class2;
};

template<>
struct Homomorphism<Class2, Class3> {
    static const Class3 morph(const Class2&) { std::cout << "Morphing in Homo<Class2, Class3>" << std::endl; return Class3{}; }
    static constexpr bool is_instance = false;
    using src  = Class2;
    using dest = Class3;
};

template<typename S, typename T, typename U,
         typename HST = typename SelectMorphism<S, T>::type,
         typename HTU = typename SelectMorphism<T, U>::type,
         typename HSU = typename SelectMorphism<S, U>::type >
struct CompositionMorphism : HSU {
    static const U morph(const S &s) {
        return HTU::morph(HST::morph(s));
    }
    static constexpr bool is_instance = true;
    using src  = S;
    using dest = U;
};

int main ()
{
    CompositionMorphism<Class1, Class2, Class3>::morph(Class1{});
}

关于c++ - 用 C++ 编写类型类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50865245/

相关文章:

c++ - 模板的丑陋编译器错误

xcode - 有什么好的Xcode脚本可以加快开发速度?

perl - 如何直接插入存储?

c++ - 通过引用而不是通过值从函数中获取对象

c++ - 为什么不能在 Boost.Test 测试用例中创建线程?

c++ - 模板函数中的 volatile 类型推导有什么问题?

javascript - Web 组件模板错误

ruby-on-rails - Ruby:将方法添加到现有模块

c++ - 无法使用两种不同的频率为 *.wav 文件填充缓冲区

c++ - 一种使用PTX计算C++/CUDA程序中浮点运算的方法