用 C++ 编写类型类
Writing typeclasses in C++
我正在尝试用 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
.
的重复定义
有没有一种方法可以用 Homomorphism
和 Monomorphism
来编写 CompositionMorphism
及其特化,这样我就可以做一些事情,比如 call:
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
特化?
好吧,有时我需要多思考一下,但这可能就是您要找的:
#include <type_traits>
#include <cstdint>
#include <tuple>
template<typename S, typename T>
struct Homomorphism;
template<typename S, typename T>
struct Monomorphism;
class Class1{};
class Class2{};
class Class3{};
template<> struct Homomorphism<Class1, Class2>
{
static const Class2 morph(const Class1&);
static constexpr bool is_instance = true;#
};
template<> struct Homomorphism<Class2, Class3>
{
static const Class3 morph(const Class2&);
static constexpr bool is_instance = true;
};
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;
};
namespace details {
template<typename T, typename U, std::enable_if_t<Homomorphism<T,U>::is_instance>* = nullptr>
U morph (const T& t)
{return Homomorphism<T,U>::morph(t);}
template<typename T, typename U, std::enable_if_t<Monomorphism<T,U>::is_instance>* = nullptr>
U morph (const T& t)
{return Monomorphism<T,U>::morph(t);}
}
template <typename S, typename T, typename U>
class CompositionMorphism
{
public:
static U morph (const S& s) {return details::morph<T,U>(details::morph<S,T>(s));}
static constexpr bool is_instance = true;
};
int main(int, char**)
{
Class1 c1Instance;
CompositionMorphism<Class1, Class2, Class3>::morph(c1Instance);
std::ignore = d;
}
并且您可能想要手动创建复合 Homo/Mono 态射,如下所示:
template <> class Monomorphism<Class1,Class3> : public CompositionMorphism<Class1, Class2, Class3> {};
然后它们可以被 CompositionMorphism 自动重用。
您可以尝试在 morph
函数上基于 SFINAE 编写 select Homomorphism
或 Monomorphism
的模板。
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)
是否会 return 一个 T
,如果是 select 一个 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{});
}
根据 Super 的观察,如果您仅传递 T
、U
和 V
,编译器不知道是否选择 Homomorphism
或 Monomorphism
.
所以我想你应该通过Homomorphism<T, U>
和Homomorphism<U, V>
(Homomorphism<T, V>
可以构造)或者Monomorphism<T, U>
和Monomorphism<U, V>
如果你想强加两个 Homomorphism
或 两个 Monomorphism
(我的意思是:如果你想排除一个 Monomorphism
和一个 Homomorphism
) 你可以这样写
template <typename, typename>
struct CompositionMorphism;
template <template <typename, typename> class C,
typename S, typename T, typename U>
struct CompositionMorphism<C<S, T>, C<T, U>>
{
using comp = C<S, U>;
static const U morph (const S & s)
{ return C<T, U>::morph(C<S, T>::morph(s)); }
};
并如下调用
Homomorphism<int, long> h0;
Homomorphism<long, long long> h1;
Monomorphism<int, long> m0;
Monomorphism<long, long long> m1;
CompositionMorphism<decltype(h0), decltype(h1)> h2;
CompositionMorphism<decltype(m0), decltype(m1)> m2;
// compiler error
//CompositionMorphism<decltype(h0), decltype(m1)> hm;
下面是一个完整的编译示例
#include <array>
#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, typename>
struct CompositionMorphism;
template <template <typename, typename> class C,
typename S, typename T, typename U>
struct CompositionMorphism<C<S, T>, C<T, U>>
{
using comp = C<S, U>;
static const U morph (const S & s)
{ return C<T, U>::morph(C<S, T>::morph(s)); }
};
int main ()
{
Homomorphism<int, long> h0;
Homomorphism<long, long long> h1;
Monomorphism<int, long> m0;
Monomorphism<long, long long> m1;
CompositionMorphism<decltype(h0), decltype(h1)> h2;
CompositionMorphism<decltype(m0), decltype(m1)> m2;
// compiler error
//CompositionMorphism<decltype(h0), decltype(m1)> hm;
static_assert( std::is_same<Homomorphism<int, long long>,
decltype(h2)::comp>{}, "!" );
static_assert( std::is_same<Monomorphism<int, long long>,
decltype(m2)::comp>{}, "!" );
}
我正在尝试用 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
.
有没有一种方法可以用 Homomorphism
和 Monomorphism
来编写 CompositionMorphism
及其特化,这样我就可以做一些事情,比如 call:
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
特化?
好吧,有时我需要多思考一下,但这可能就是您要找的:
#include <type_traits>
#include <cstdint>
#include <tuple>
template<typename S, typename T>
struct Homomorphism;
template<typename S, typename T>
struct Monomorphism;
class Class1{};
class Class2{};
class Class3{};
template<> struct Homomorphism<Class1, Class2>
{
static const Class2 morph(const Class1&);
static constexpr bool is_instance = true;#
};
template<> struct Homomorphism<Class2, Class3>
{
static const Class3 morph(const Class2&);
static constexpr bool is_instance = true;
};
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;
};
namespace details {
template<typename T, typename U, std::enable_if_t<Homomorphism<T,U>::is_instance>* = nullptr>
U morph (const T& t)
{return Homomorphism<T,U>::morph(t);}
template<typename T, typename U, std::enable_if_t<Monomorphism<T,U>::is_instance>* = nullptr>
U morph (const T& t)
{return Monomorphism<T,U>::morph(t);}
}
template <typename S, typename T, typename U>
class CompositionMorphism
{
public:
static U morph (const S& s) {return details::morph<T,U>(details::morph<S,T>(s));}
static constexpr bool is_instance = true;
};
int main(int, char**)
{
Class1 c1Instance;
CompositionMorphism<Class1, Class2, Class3>::morph(c1Instance);
std::ignore = d;
}
并且您可能想要手动创建复合 Homo/Mono 态射,如下所示:
template <> class Monomorphism<Class1,Class3> : public CompositionMorphism<Class1, Class2, Class3> {};
然后它们可以被 CompositionMorphism 自动重用。
您可以尝试在 morph
函数上基于 SFINAE 编写 select Homomorphism
或 Monomorphism
的模板。
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)
是否会 return 一个 T
,如果是 select 一个 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{});
}
根据 Super 的观察,如果您仅传递 T
、U
和 V
,编译器不知道是否选择 Homomorphism
或 Monomorphism
.
所以我想你应该通过Homomorphism<T, U>
和Homomorphism<U, V>
(Homomorphism<T, V>
可以构造)或者Monomorphism<T, U>
和Monomorphism<U, V>
如果你想强加两个 Homomorphism
或 两个 Monomorphism
(我的意思是:如果你想排除一个 Monomorphism
和一个 Homomorphism
) 你可以这样写
template <typename, typename>
struct CompositionMorphism;
template <template <typename, typename> class C,
typename S, typename T, typename U>
struct CompositionMorphism<C<S, T>, C<T, U>>
{
using comp = C<S, U>;
static const U morph (const S & s)
{ return C<T, U>::morph(C<S, T>::morph(s)); }
};
并如下调用
Homomorphism<int, long> h0;
Homomorphism<long, long long> h1;
Monomorphism<int, long> m0;
Monomorphism<long, long long> m1;
CompositionMorphism<decltype(h0), decltype(h1)> h2;
CompositionMorphism<decltype(m0), decltype(m1)> m2;
// compiler error
//CompositionMorphism<decltype(h0), decltype(m1)> hm;
下面是一个完整的编译示例
#include <array>
#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, typename>
struct CompositionMorphism;
template <template <typename, typename> class C,
typename S, typename T, typename U>
struct CompositionMorphism<C<S, T>, C<T, U>>
{
using comp = C<S, U>;
static const U morph (const S & s)
{ return C<T, U>::morph(C<S, T>::morph(s)); }
};
int main ()
{
Homomorphism<int, long> h0;
Homomorphism<long, long long> h1;
Monomorphism<int, long> m0;
Monomorphism<long, long long> m1;
CompositionMorphism<decltype(h0), decltype(h1)> h2;
CompositionMorphism<decltype(m0), decltype(m1)> m2;
// compiler error
//CompositionMorphism<decltype(h0), decltype(m1)> hm;
static_assert( std::is_same<Homomorphism<int, long long>,
decltype(h2)::comp>{}, "!" );
static_assert( std::is_same<Monomorphism<int, long long>,
decltype(m2)::comp>{}, "!" );
}