C++ 概念看到我的类型的函数,但看不到 std::vector
C++ concepts see a function for my type, but don't see it for std::vector
我正在尝试使用 Functor、Monoid 等类型类在 C++ 中实现类似 Haskell Prelude 的东西。所以我决定使用 C++ 概念来进行类型检查,但是我在尝试实现 Semigroup 概念时遇到了问题。
当我尝试声明一个使用某些函数的概念时出现问题,该函数稍后在代码中为所需类型声明和重载,但它仅与 std::vector 等某些类型相关,但与我自己的类型相关类型效果很好。
完整代码:
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.
我认为这是这个实验性 Clang 概念实现中的一个缺陷。 [temp.concept]/8 说:
A concept is not instantiated ([temp.spec]).
另请参阅:In which access control context are evaluated concepts?
这意味着 [temp.res] 中描述的名称解析不适用于作为概念定义的表达式。如果必须实例化概念,则无法通过非限定名称 look-up 找到函数 add
。这就是 Clang 产生错误的原因。
按照标准,当id-expression命名一个概念时,normalized constraint-expression is evaluated where appears the id-expression ([expr.prim.id]/4).
不那么正式,作为概念定义的表达式是在命名概念的表达式的上下文中计算的。所以 Addable<vector<int>>
应该是真的,因为在这个表达式的上下文中, add
可以通过非限定名称 look-up.
找到
我正在尝试使用 Functor、Monoid 等类型类在 C++ 中实现类似 Haskell Prelude 的东西。所以我决定使用 C++ 概念来进行类型检查,但是我在尝试实现 Semigroup 概念时遇到了问题。
当我尝试声明一个使用某些函数的概念时出现问题,该函数稍后在代码中为所需类型声明和重载,但它仅与 std::vector 等某些类型相关,但与我自己的类型相关类型效果很好。
完整代码:
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.
我认为这是这个实验性 Clang 概念实现中的一个缺陷。 [temp.concept]/8 说:
A concept is not instantiated ([temp.spec]).
另请参阅:In which access control context are evaluated concepts?
这意味着 [temp.res] 中描述的名称解析不适用于作为概念定义的表达式。如果必须实例化概念,则无法通过非限定名称 look-up 找到函数 add
。这就是 Clang 产生错误的原因。
按照标准,当id-expression命名一个概念时,normalized constraint-expression is evaluated where appears the id-expression ([expr.prim.id]/4).
不那么正式,作为概念定义的表达式是在命名概念的表达式的上下文中计算的。所以 Addable<vector<int>>
应该是真的,因为在这个表达式的上下文中, add
可以通过非限定名称 look-up.