在C ++中,haskell下划线是否可以替代?

时间:2019-07-01 17:40:49

标签: c++ templates

让我们想象一下,我在c ++中有类似haskell的类Maybe。例如,可以这样实现:

template<typename T, typename val> 
struct Maybe;

template<typename val> struct Maybe<std::true_type, val> {  
    using value = val; 
};

template<> struct Maybe<std::false_type, void> {

};

template<typename val> 
using Just = Maybe<std::true_type, val>;

using Nothing = Maybe<std::false_type, void>;

我想使用“等于”函数对它们进行比较:

template<typename T, typename R>
struct equal;

如果我有实例<Just<T>, Just<R>>,则需要同时使用类型TR来知道比较的结果,但是如果是<Just<T>, Nothing>或{{1} }我不需要了解有关T类型的任何信息。在haskell中,您可以使用下划线(<Nothing, Just<T>>),但是c ++中有类似的东西吗?

3 个答案:

答案 0 :(得分:0)

不知道您想要什么,但是...我想您想要的东西

template <typename, typename>
struct JustEqual : public std::false_type
 { };

template <typename T>
struct JustEqual<Just<T>, Just<T>> : public std::true_type
 { };

通过这种方式,JustEqualstd::true_type继承(当且仅当)两个类型名都是同一Just<T>的{​​{1}}类型。

当类型名称是用于不同类型的T类型,或者是Just类型和Just或两个Nothing时,Nothing专业化不会匹配,并且仅匹配主要版本(从JustEqual继承)。

以这种方式观察,std::false_type仅与主版本匹配,因此从JustEqual<Nothing, Nothing>继承。我不清楚这是否是您想要的。

如果您希望std::false_type继承自JustEqual<Nothing, Nothing>,则可以添加特定的专业化名称

std::true_type

答案 1 :(得分:0)

我相信_是模板参数的有效标识符,但是省略typename _可以防止将其识别为模板参数。因此,最接近的可以是这样:

template<typename T, typename R>
struct equal;

template<typename T, typename R>
struct equal<Just<T>, Just<R>> {
    using value = typename std::conditional<std::is_same<T, R>::value, True, False>::type;
};

template<typename _>
struct equal<Just<_>, Nothing> {
    using value = False;
};

template<typename _>
struct equal<Nothing, Just<_>> {
    using value = False;
};

template<>
struct equal<Nothing, Nothing> {
    using value = True;
};

答案 2 :(得分:0)

这不能回答您有关模板参数的通配符类型的问题。

针对您的特定问题,如果您用equal而不是MaybeJust来定义Nothing,则可以简化对Maybe的定义。重要的是Nothing的两个参数必须相同,因此equal也是如此。

这可以简化False的定义,因为现在它可以默认为template<typename, typename> struct equal { using value = False; }; template<typename B, typename V> struct equal<Maybe<B, V>, Maybe<B, V>> { using value = True; };

p1.distanceTo(p2);

Try it online!