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

考虑这个例子:

#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 Worldn";
    }
};

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.


我发现错误来自autoin constexpr auto is_printable() { ... },替换autowithbool将正确编译。

template<typename T>
constexpr bool is_printable() {
    return Printable<T>;
}

我觉得这很奇怪,这个概念Printable<T>是在编译时评估的,应该生成一个constexpr bool. 为什么auto会突然失败?

回答

这是一个 MSVC 错误。你的代码是正确的。我强烈建议报告这个问题。您的代码在 GCC 和 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 Worldn";
    }
};

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();
}


以上是未能在SFINAE中将概念类型识别为bool的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>