boost is_invocable_v и is_invocable :: value возвращают разные результаты - PullRequest
1 голос
/ 09 мая 2020

Поскольку мне пришлось написать код, совместимый с C ++ 14, где я все еще хотел использовать std::is_invocable в шаблоне, я попытался использовать boost::callable_traits::is_invocable. Однако, хотя boost::callable_traits::is_invocable вернул аналогичные результаты, boost::callable_traits::is_invocable_v не вернул.

Вот простой пример поведения:

#include <iostream>
#include <boost/callable_traits.hpp>
#include <type_traits>
#include <boost/version.hpp>

int test(int){
    return 0;
}

int main()
{
    std::cout << "Boost version: " << BOOST_LIB_VERSION << std::endl;
    std::cout<< "boost::callable_traits::is_invocable_v: "
        << boost::callable_traits::is_invocable_v<decltype(test), int> << std::endl;
    std::cout<< "boost::callable_traits::is_invocable: "
        << boost::callable_traits::is_invocable<decltype(test), int>::value << std::endl;
    std::cout<< "std::is_invocable_v: "
        << std::is_invocable_v<decltype(test), int> << std::endl;
    std::cout<< "std::is_invocable: "
        << std::is_invocable<decltype(test), int>::value << std::endl;

    return 0;
}

Результат:

Boost version: 1_72
boost::callable_traits::is_invocable_v: 0
boost::callable_traits::is_invocable: 1
std::is_invocable_v: 1
std::is_invocable: 1

Я загрузил код также в wandbox .

В чем причина такого удивительного поведения?

1 Ответ

1 голос
/ 09 мая 2020

Мне это кажется ошибкой Boost. is_invocable и is_invocable_v имеют разные реализации (взяты из Boost 1.69, комментарий мой):

template<typename T, typename... Args>
struct is_invocable : detail::is_invocable_impl<T, Args...>::type {
    using type = typename detail::is_invocable_impl<T, Args...>::type;
};

template<typename T, typename... Args>
constexpr bool is_invocable_v =
    detail::is_invocable_impl<detail::traits<T>, Args...>::type::value;

//                            ^^^^^^^^^^^^^^^^^ Why?

Думаю, detail::traits<T> должно быть просто T. В вашем конкретном примере detail::traits<T> это detail::function<int(int)>. Его возможность вызова не имеет ничего общего с возможностью вызова test.

...