-
Notifications
You must be signed in to change notification settings - Fork 887
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
std::tuple of no default constructible class makes compile error on MSVC2015 C++11 build #343
Comments
I analyzed a little and created a minimal code that reproduce the problem. See the following code: #include <tuple>
#include <utility>
template<bool...> struct bool_pack;
template<bool...values> struct all_of_imp
: std::is_same<bool_pack<values..., true>, bool_pack<true, values...>> {};
template<template <class> class T, class... U>
using all_of = all_of_imp<T<U>::value...>;
template <typename T, typename Enabler = void>
struct as;
template <typename T>
struct has_as {
private:
template <typename U>
static auto check(U*) -> typename std::is_same<decltype(as<U>()()), T>::type;
template <typename>
static std::false_type check(...);
public:
using type = decltype(check<T>(nullptr));
static constexpr bool value = type::value;
};
template <typename... Args>
struct as<std::tuple<Args...>, typename std::enable_if<all_of<has_as, Args...>::value>::type> {
std::tuple<Args...> operator()() const {
return std::tuple<Args...>();
}
};
struct my {};
template <>
struct as<my> {
my operator()() const {
return my();
}
};
template <typename T, typename U>
typename std::enable_if<all_of<has_as, T, U>::value>::type foo(std::tuple<T, U> const&) {}
template <typename... Args>
typename std::enable_if<all_of<has_as, Args...>::value>::type bar(std::tuple<Args...> const&) {}
int main() {
static_assert(all_of<has_as, my, my>::value, ""); // OK
foo(std::tuple<my, my>()); // OK
bar(std::tuple<my>()); // OK
bar(std::tuple<my, my>()); // ERROR on MSVC2015
} clang++ and g++ have no compile errors. However, MSVC2015 produced the following compile error:
The original problem that requires default constructor is the result of specialization failure. When the specialization failure, 'as' is fallbacked into 'convert'. 'convert' requires a default constructor. This code reproduce the specialization failure. I guess that there are some variadic template parameters related problems on MSVC2015. Consider the following code: foo(std::tuple<my, my>()); // OK
bar(std::tuple<my>()); // OK
bar(std::tuple<my, my>()); // ERROR on MSVC2015 foo() with two template arguments compiled successfully. foo()'s enable_if has two template parameters. bar() with one template argument compiled successfully. bar()'s enable_if has variadic template parameters. template <typename T, typename U>
typename std::enable_if<all_of<has_as, T, U>::value>::type foo(std::tuple<T, U> const&) {}
template <typename... Args>
typename std::enable_if<all_of<has_as, Args...>::value>::type bar(std::tuple<Args...> const&) {} |
I found the reason of this behavior. First, MSVC2015 doesn't support Expression SFINAE yet. See: And according to the following post, they will support it in a future update: msgpack-c checks 'as' class template specialization that has operator()(msgpack::object const&). A User can define the specialization for a user defined classe to support non-default-constructible class or to achive move based efficient implementation on C++11. If the specialization is not found, msgpack-c uses 'convert' class template as a fallback. And 'convert' class template requires default constructor of the user type. To check 'as' class template specialization existance, msgpack-c uses Expression SFINAE. ConclusionWe can use msgpack-c's C++11 functionality on MSVC2015 except non-default-constructible support using 'as' class template specialization. In the current implementation, when the number of template arguments is one, Expression SFINAE works as expected by chance. So 'as' class template specialization's operator() is dispatched as expected. However, we shouldn't depend on this implementation because Microsoft offically said that they don't support Expression SFINAE yet. When we use MSVC2015 with C++11 msgpack-c, don't define 'as' class template specialization until MSVC2015 would support Expression SFINAE. |
See:
#339 (comment)
When the line *1 uncomment, I got the following compile error:
The error message indicates line 27:
std::tuple<no_def_con> val1{ 1 };
but the line 36:
o.as<std::tuple<no_def_con, no_def_con>>(); // ERROR *1
causes the compile error.
If the elements of the std::tuple is one, no errors are occurred, if the elements of the std::tuple are two or more, the compile error occurs.
This compile error only happens C++11 msgpack-c, So you can avoid the compile error with MSGPACK_USE_CPP03 macro definition.
I analyzed msgpack-c code. I think that https://github.com/msgpack/msgpack-c/blob/master/include/msgpack/adaptor/cpp11/tuple.hpp#L75 is something relate to the problem. This code works well on Linux with libstdc++ and osx with libc++. I think that MSVC2015's tuple implementation might have a problem. But I couldn't write a minimal code that reproduces the problem.
Any help is welcome.
The text was updated successfully, but these errors were encountered: