c++ - 未能在 SFINAE 中将概念类型识别为 bool

标签 c++ c++20 sfinae c++-concepts

考虑这个例子:

#include <iostream>
#include <utility>

template<typename T>
concept Printable = requires(const T a) {
    a.print();
};
template<typename T>
constexpr auto is_printable() {
    return Printable<T>;
}

template<class T, std::enable_if_t<is_printable<T>()>* = nullptr>
constexpr void do_print(T data) {
    data.print();
}

struct foo {
    void print() const {
        std::cout << "Hello World\n";
    }
};

int main() {
    foo f;
    do_print(f);
}
尝试在 MSVC(版本 16.9.4,/std:c++latest)上编译它会产生以下错误:
Error   C2783   'void do_print(T)': could not deduce template argument for '__formal'
Error   C2672   'do_print': no matching overloaded function found
它未能满足 std::enable_if_t .

我发现错误来自 autoconstexpr auto is_printable() { ... } ,并替换 autobool将正确编译。
template<typename T>
constexpr bool is_printable() {
    return Printable<T>;
}
我觉得这很奇怪,这个概念 Printable<T>在编译时评估,应该产生 constexpr bool .为什么auto突然失败?

最佳答案

这是一个 MSVC 错误。你的代码是正确的。我强烈建议报告这个问题。 Your code works correctly on GCC and Clang .

与此同时,我会简单地放弃 SFINAE。当您获得替换 enable ifs 的概念时,实际上并不需要它:

#include <iostream>
#include <utility>

template<typename T>
concept Printable = requires(const T a) {
    a.print();
};

constexpr void do_print(Printable auto data) {
    data.print();
}

struct foo {
    void print() const {
        std::cout << "Hello World\n";
    }
};

int main() {
    foo f;
    do_print(f);
}
您也可以使用 requires甚至替换 typename与您的概念:
template<typename T> requires Printable<T>
constexpr void do_print(T data) {
    data.print();
}

template<Printable T>
constexpr void do_print(T data) {
    data.print();
}

关于c++ - 未能在 SFINAE 中将概念类型识别为 bool,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/67165504/

相关文章:

C++20 Module 多层继承

C++ 检查语句是否可以评估 constexpr

c++ - 如何为 C++ 重载解析和 SFINAE 编写正/负测试?

c++ - "lazy man' s enable_if"是合法的 C++ 吗?

C++ &array 和 array 的用法有什么区别?

c++ - 闪存数据格式

c++ - 虚拟 constexpr 协变返回类型

c++ - 通过 SFINAE GCC 错误测试 std::ostream operator<< 是否存在?

c++ - 如何根据对象的状态更改对象的接口(interface)?

javascript - 在 IE9 上使用 DISPID_NEWENUM 使用 C++ 检索 javascript 数组对象失败