模板类型上std :: is_invocable的意外结果

如何解决模板类型上std :: is_invocable的意外结果

我有一个if constexpr检查类型是否与其自身相等。我使用std::is_invocable_v<std::equal_to<>,T,T>

但是,当T是无与伦比的结构的向量时,该代码错误地返回True。有深层原因吗?还是编译器错误

下面是最小的示例。

#include <type_traits>
#include <iostream>
#include <vector>

class TNonComparable{};

int main()
{
    std::cout << std::is_invocable_v<std::equal_to<>,TNonComparable,TNonComparable> << "\n";
    // 0

    std::cout << std::is_invocable_v<
            std::equal_to<>,std::vector<TNonComparable>,std::vector<TNonComparable>
        > << "\n";
    // 1

    std::vector<TNonComparable> vec;
    // vec == vec;
    // (expected) compilation error
}

我检查了Godbolt的输出,所有最新版本的g ++和clang都一样。

解决方法

我认为look at std::is_invocable的作用非常重要:

确定是否可以使用参数Fn调用ArgTypes...。 正式确定INVOKE(declval<Fn>(),declval<ArgTypes>()...) 在被视为未评估值时是否格式正确 操作数,其中INVOKECallable 中定义的操作。

强调地雷。

这里要注意的重要部分是,std::equal_to<>中使用的std::is_invocable永远不会被求值,因为它是未求值的操作数。这意味着它仅检查operator==是否存在,而对std::vector<>这样做,而不检查它是否可以在评估的上下文中进行编译。

,

我认为这是正确的行为。

在第一个std::is_invokable_v中检查operator==类型的TNonComparable的存在。它不存在-结果为0。

在第二种情况下,std::is_invokable_v检查std::vector的相等运算符,该运算符存在并且可以被调用。但是,如果要尝试调用它,它将无法编译,因为TNonComparable类型没有operator==。但是在您不尝试使用它之前,它不会产生错误。

也许,在第二种情况下,您应该检查std :: vector的value_type:

std::cout << std::is_invocable_v<
        std::equal_to<>,std::vector<TNonComparable>::value_type,std::vector<TNonComparable>::value_type
    > << "\n";
// 0
,

花了一些时间,我已经写了解决方法工具

namespace detail
{
    template<typename T,typename=void>
    struct has_value_type : std::false_type {};

    template<typename T>
    struct has_value_type<T,std::void_t<typename T::value_type>> : std::true_type {};

    template<typename T,typename=void>
    struct is_pair : std::false_type {};

    template<typename T,typename U>
    struct is_pair<std::pair<T,U>,void> : std::true_type {};

    template<typename T,typename=void>
    struct is_tuple : std::false_type {};

    template<typename ...Args>
    struct is_tuple<std::tuple<Args...>,void> : std::true_type {};
}

template<typename T,typename=void>
struct has_euqual_operator : std::false_type {};

template<typename T>
struct has_euqual_operator<
        T,std::void_t<
            std::enable_if_t<
                !detail::is_pair<T>::value 
                && !detail::has_value_type<T>::value 
                && !detail::is_tuple<T>::value>,decltype(std::declval<T>() == std::declval<T>())
        >
    > : std::true_type 
{};

template<typename T>
struct has_euqual_operator<
        T,std::enable_if_t<has_euqual_operator<typename T::value_type>::value>
    > : std::true_type 
{};

template<typename T>
struct has_euqual_operator<
        T,std::enable_if_t<has_euqual_operator<typename T::first_type>::value
            && has_euqual_operator<typename T::second_type>::value
        >
    > : std::true_type 
{};

template<typename ...Args>
struct has_euqual_operator<
        std::tuple<Args...>,std::enable_if_t<(... && has_euqual_operator<Args>::value)>
    > : std::true_type 
{};

https://godbolt.org/z/rcejhx

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?
Java在半透明框架/面板/组件上重新绘画。
Java“ Class.forName()”和“ Class.forName()。newInstance()”之间有什么区别?
在此环境中不提供编译器。也许是在JRE而不是JDK上运行?
Java用相同的方法在一个类中实现两个接口。哪种接口方法被覆盖?
Java 什么是Runtime.getRuntime()。totalMemory()和freeMemory()?
java.library.path中的java.lang.UnsatisfiedLinkError否*****。dll
JavaFX“位置是必需的。” 即使在同一包装中
Java 导入两个具有相同名称的类。怎么处理?
Java 是否应该在HttpServletResponse.getOutputStream()/。getWriter()上调用.close()?
Java RegEx元字符(。)和普通点?