我正在拉链上实现一些功能,其中孔类型是存在量化的,即我有这样的东西:
data Zipper (c :: Type -> Constraint) ... =
forall hole. (c hole, ...) =>
Zipper hole ...
Run Code Online (Sandbox Code Playgroud)
dot表示我认为与我的问题无关的实现细节.现在考虑一些数据类型:
data Tree = Fork Tree Tree | Leaf Int
Run Code Online (Sandbox Code Playgroud)
我想拥有的是检查我在树上的位置的能力.在简单递归的情况下,实现此目的的标准方法是模式匹配:
case hole of
Fork _ _ -> doSomething
Leaf _ -> doSomethingElse
Run Code Online (Sandbox Code Playgroud)
然而,孔的类型是存在量化的,因此简单的模式匹配是不可行的.我的想法是使用类型类
class WhereAmI p a where
position :: a -> p a
data Position :: Type -> Type where
C_Leaf :: Position Tree
C_Fork :: Position Tree
-- possibly more constructors if we're traversing
-- multiple data structures …Run Code Online (Sandbox Code Playgroud) 考虑一个简单的效用函数来计算连接,并使用此实用程序来确保a std::tuple中的类型都相等.
#include <type_traits>
#include <tuple>
constexpr auto all() noexcept -> bool { return true; }
template <class... Bools>
constexpr auto all(bool const x, Bools... xs) noexcept -> bool
{
return x && all(xs...);
}
template <class T, class = void>
struct foo;
template <class T, class... Ts>
struct foo< std::tuple<T, Ts...>
, std::enable_if_t<all(std::is_same<T, Ts>::value...)>
> {
};
int main()
{
foo<std::tuple<int, int>> x;
}
Run Code Online (Sandbox Code Playgroud)
GCC和Clang对此代码很好,但MSVC不是.这是一个Godbolt链接.所以我想知道,这是一个MSVC错误还是只是我错过了什么?
考虑以下简单的仅移动类:
struct bar {
constexpr bar() = default;
bar(bar const&) = delete;
bar(bar&&) = default;
bar& operator=(bar const&) = delete;
bar& operator=(bar&&) = default;
};
Run Code Online (Sandbox Code Playgroud)
现在,让我们创建一个包装器:
template <class T>
struct box {
constexpr box(T&& x)
: _payload{std::move(x)}
{}
constexpr explicit operator T() &&
{
return std::move(_payload);
}
private:
T _payload;
};
Run Code Online (Sandbox Code Playgroud)
并测试:
int main()
{
auto x = box<bar>{bar{}};
auto y = static_cast<bar&&>(std::move(x));
}
Run Code Online (Sandbox Code Playgroud)
如果使用-std=c++14或以上编译,Clang-6.0对此代码感到满意.但是,GCC-8.1会产生以下错误:
<source>: In function 'int main()':
<source>:29:45: error: invalid static_cast from type 'std::remove_reference<box<bar>&>::type' {aka …Run Code Online (Sandbox Code Playgroud)