【发布时间】:2019-06-08 20:25:18
【问题描述】:
我正在尝试使用 Functor、Monoid 等类型类在 C++ 中实现类似 Haskell Prelude 之类的东西。所以我决定使用 C++ Concepts 进行类型检查,但在尝试实现 Semigroup 概念时遇到了问题。
当我尝试声明一个使用某些函数的概念时出现问题.
完整代码:
template<class T>
struct S {
// ...
};
template<class T>
concept Addable = requires(T a, T b) {
{ add(a, b) } -> T;
};
template<class T>
S<T> add(const S<T> & a, const S<T> & b) {
// ...
return {};
}
template<class T>
std::vector<T> add(const std::vector<T> & a, const std::vector<T> & b) {
// ...
return {};
}
int main() {
std::cout << Addable<S<int>> << '\n';
std::cout << Addable<std::vector<int>> << '\n';
}
我希望输出1 1,但实际输出是1 0。
因此,无论声明的 add(std::vector) 重载如何,它都不会将 std::vector 识别为 Addable,但它确实将 S 类型识别为 Addable。
统一更新:
如果我将add 函数移到Addable 概念之前,问题就会消失。但是,在包含这些概念之前,我必须实现我为 std::vector 之类的类型包含的所有概念,这看起来非常不方便且不清楚。
UPD2: 我使用 GCC 9.1.0。
【问题讨论】:
-
我的猜测是,
Addable通过与参数相关的查找为S找到add,但不能为vector做同样的事情,因为类和函数位于不同的命名空间中.如果在Addable之前声明或定义add是否有效? -
@chris 就像我想的那样——一旦你将
Addable向下移动,所以add对普通查找可见,程序会打印1 1 -
请注意,如果您未能通过重载决议检查as seen here,Clang 会为您提供一些关于为什么的更多信息。
-
@IgorTandetnik 这是否意味着如果我有来自 stl 的
std::vector和来自第三方库的一些Addable概念,我将无法为 @987654340 实现该概念@?或者我只能通过在包含Addable的标题之前放置add来做到这一点?
标签: c++ templates stdvector c++-concepts