I wrote a template class RWHelper
, and wanted to use it to write iterators. But it failed to compiled in VS2019 toolset=v140, which is c++11. On the other hand, it's passed in c++14, which means VS2019 toolset=v142. The compilation error is as follows: error C2955: std::decay: use of class template requires template argument list
, and I don't know why the expression defer\<It\>
in std::decay\<defer\<It\>\>::type
is not deduced.
#include <iostream>
#include <type_traits>
#include <typeinfo>
#include <cstdint>
#include <vector>
#include <string>
namespace detail
{
template <typename T>
using void_t = void;
template <template <class...> class Test, class, class... Args>
struct is_detected : std::false_type {};
template <template <class...> class Test, class... Args>
struct is_detected<Test, void_t<Test<Args...>>, Args...> : std::true_type {};
template <typename T>
using is_explicitly_dereferenceable_test = decltype(std::declval<T>().operator*());
template <template <class> class Test, class, class Args>
struct defer { typedef typename std::remove_pointer<typename std::decay<Args>::type>::type type; };
template <template <class> class Test, class Args>
struct defer<Test, void_t<Test<Args>>, Args> { typedef Test<Args> type; };
}
template <template <class...> class Trait, class... Args>
using is_detected = typename detail::is_detected<Trait, void, Args...>::type;
template <typename T>
using is_pointer_like = std::integral_constant<bool,
!std::is_array<T>::value &&
(std::is_pointer<T>::value || is_detected<detail::is_explicitly_dereferenceable_test, T>::value)
>;
template<typename T>
using defer= typename detail::defer<detail::is_explicitly_dereferenceable_test, void, T>::type;
namespace utility
{
class RWHelper
{
public:
template <typename It>
void Write(It first, It last)
{
Write<It, typename std::decay<defer<It>>::type>(first, last,
std::integral_constant < bool,
is_pointer_like<It>::value &
std::is_same<
typename std::decay<decltype(*std::declval<It>())>::type,
std::string
>::value
>()
);
}
template <typename It, typename Item>
void Write(It first, It last, std::false_type)
{
std::cout << "[1]: {It = " << typeid(It).name() << ", Item = " << typeid(Item).name() << "}" << std::endl;
}
template <typename It, typename Item>
void Write(It first, It last, std::true_type) {
std::cout << "[2]: {It = " << typeid(It).name() << ", Item = " << typeid(Item).name() << "}" << std::endl;
}
};
}
int main()
{
utility::RWHelper h;
// the following commented code can't be compiled in c++11 and report an error (see the title)
// but it's well in C++14. I don't know why
/*{
char s[] = { "adsf" };
h.Write( s + 0, s + 5);
std::cout << std::endl;
}*/
{
std::string s{ "sdfasdf" };
h.Write( s.begin(), s.end());
std::cout << std::endl;
}
return 0;
}
Aucun commentaire:
Enregistrer un commentaire