C++ 如何避免这个讨厌的概念陷阱(取决于顺序)

C++ 如何避免这个讨厌的概念陷阱(取决于顺序),c++,templates,compiler-warnings,c++20,c++-concepts,C++,Templates,Compiler Warnings,C++20,C++ Concepts,下面的代码取决于该概念是在类之前还是之后定义的。其目的是检查是否可以从T构造数量。我已经剥离了它,只显示了副本构造的测试 template <typename T> concept is_compatible = requires( T & t ) { Quantity( t ); }; // note: not Quantity<T> ! template <typename T> class Quantity {}; class X{};

下面的代码取决于该概念是在类之前还是之后定义的。其目的是检查是否可以从
T
构造
数量
。我已经剥离了它,只显示了副本构造的测试

template <typename T>
concept is_compatible = requires( T & t ) { Quantity( t ); }; // note: not Quantity<T> !

template <typename T>
class Quantity
{};

class X{};        

int main() 
{

    std::cout << is_compatible<Quantity<X>>;
    std::cout << is_compatible<X>;
}
模板
概念兼容=要求(T&T){数量(T)};//注意:不是数量!
模板
班级数量
{};
类X{};
int main()
{
标准::cout
这可能有一个“很好的理由”,“因为编译器以某种方式工作”,但我发现这有很大的缺陷

没有它,概念就没有那么有用。您将无法检查依赖ADL的函数调用表达式是否有效。这对声明满足了您的概念

namespace ns {
    struct X {};
    void Quantity(X) {}
}
即使在
ns
之前定义了
是否兼容
,它也会得到满足

现在,如果您的概念与ADL无关,并且您的表达式实际上是一个函数样式转换,那么只需限定类型(或模板名称)

模板
概念兼容=要求(T&T){::数量(T);};
//^——如果没有前面的声明,此处出现错误

Related是的,在写了这个问题后,我发现
Quantity
可以是任何函数。不过,我不明白为什么“ADL阶段”如果可以找到任何函数,将找不到复制构造函数…叹气。@非用户-ADL只找到免费函数sure,返回学校facepalm。
:Quantity
:gcc(当然)正确地在类前面发出错误。MSVC(理解简单人的编译器)在这两种情况下编译并执行预期的操作。然而,intellisense仍然会在错误之前或之后处理错误。这是一个混乱的世界。(是的,我知道概念还没有准备好)首先,我讨厌这种“检查复制构造函数/转换”,我真正想做的是检查
T
是否已经是
Quantity
@non-user-MSVC对模板的处理默认是非标准的。你必须显式关闭许可模式,以获得标准一致性的外观。至于检查
T
是一种
数量
专门化,可以通过一个简单的类型特征(甚至在C++98中)来实现。这个概念只需要包装它。
template <typename T>
concept is_compatible = requires( T & t ) { ::Quantity( t ); };
                                          // ^ -- in the absence of a preceding declaration, error here