Skip to content

Commit

Permalink
Basic MSVC support
Browse files Browse the repository at this point in the history
Add some required macro expentions, and work around a couple of issues

Note, qmake needs to be run with an extra argument:

  DEFINES+="__cpp_constexpr=201304 __cpp_variable_templates=201304"

so that the C++14 defines in qt are active.

Also, the tests inside the qt durectory have class with too many
invokable method and it reaches the recursion limit

Issue: #6
  • Loading branch information
ogoffart committed Jan 10, 2018
1 parent 356f8d5 commit 064747e
Show file tree
Hide file tree
Showing 2 changed files with 36 additions and 17 deletions.
40 changes: 27 additions & 13 deletions src/wobjectdefs.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,8 @@ template<> struct make_index_sequence_helper<1> { using result = index_sequence<
template<> struct make_index_sequence_helper<0> { using result = index_sequence<>; };
template<int N> using make_index_sequence = typename make_index_sequence_helper<N>::result;

/* workaround for MSVC bug that can't do decltype(xxx)::foo when xxx is dependent of a template */
template<typename T> using identity_t = T;

/**
* In this namespace we find the implementation of a template binary tree container
Expand Down Expand Up @@ -477,7 +479,7 @@ struct MetaEnumInfo {
Names names;
using Values = Values_;
static constexpr uint flags = Flags;
static constexpr uint count = Values::size();
static constexpr auto count = Values::size();
};
template<typename Enum, Enum... Value> struct enum_sequence {};
// called from W_ENUM and W_FLAG
Expand Down Expand Up @@ -590,21 +592,33 @@ template <typename... Args> constexpr QOverload<Args...> qOverload = {};

#endif // Qt < 5.7

// Private macro helpers for classical macro programming

#ifdef Q_CC_MSVC
// Workaround for MSVC: expension rules are different so we need some extra macro.
#define W_MACRO_MSVC_EXPAND(...) __VA_ARGS__
#define W_MACRO_MSVC_DELAY(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__))
#define W_MACRO_MSVC_EMPTY /##* *##/
#else
#define W_MACRO_MSVC_EXPAND(...) __VA_ARGS__
#define W_MACRO_MSVC_DELAY(X,...) X(__VA_ARGS__)
#define W_MACRO_MSVC_EMPTY
#endif

// Private macro helpers for macro programming
#define W_MACRO_EMPTY
#define W_MACRO_EVAL(...) __VA_ARGS__
#define W_MACRO_DELAY(X,...) X(__VA_ARGS__)
#define W_MACRO_DELAY2(X,...) X(__VA_ARGS__)
#define W_MACRO_DELAY(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__))
#define W_MACRO_DELAY2(X,...) W_MACRO_MSVC_EXPAND(X(__VA_ARGS__))
#define W_MACRO_TAIL(A, ...) __VA_ARGS__
#define W_MACRO_FIRST(...) W_MACRO_FIRST2(__VA_ARGS__,)
#define W_MACRO_FIRST(...) W_MACRO_MSVC_EXPAND(W_MACRO_FIRST2(__VA_ARGS__,))
#define W_MACRO_FIRST2(A, ...) A
#define W_MACRO_STRIGNIFY(...) W_MACRO_STRIGNIFY2(__VA_ARGS__)
#define W_MACRO_STRIGNIFY2(...) #__VA_ARGS__
#define W_MACRO_CONCAT(A, B) W_MACRO_CONCAT2(A,B)
#define W_MACRO_CONCAT2(A, B) A##_##B

// strignify and make a StaticStringList out of an array of arguments
#define W_PARAM_TOSTRING(...) W_PARAM_TOSTRING2(__VA_ARGS__ ,,,,,,,,,,,,,,,,)
#define W_PARAM_TOSTRING(...) W_MACRO_MSVC_EMPTY W_MACRO_MSVC_DELAY(W_PARAM_TOSTRING2,__VA_ARGS__ ,,,,,,,,,,,,,,,,)
#define W_PARAM_TOSTRING2(A1,A2,A3,A4,A5,A6,A7,A8,A9,A10,A11,A12,A13,A14,A15,A16,...) \
w_internal::makeStaticStringList(#A1,#A2,#A3,#A4,#A5,#A6,#A7,#A8,#A9,#A10,#A11,#A12,#A13,#A14,#A15,#A16)

Expand Down Expand Up @@ -662,8 +676,8 @@ template <typename... Args> constexpr QOverload<Args...> qOverload = {};
W_RETURN(w_internal::binary::tree_append(STATE(w_counter.prev(), w_this), __VA_ARGS__))
#else
#define W_STATE_APPEND(STATE, ...) \
friend constexpr auto STATE(w_internal::w_number<decltype(STATE( \
w_internal::w_number<>{}, static_cast<W_ThisType**>(nullptr)))::size+1> w_counter, \
friend constexpr auto STATE(w_internal::w_number<w_internal::identity_t<decltype(STATE( \
w_internal::w_number<>{}, static_cast<W_ThisType**>(nullptr)))>::size+1> w_counter, \
W_ThisType **w_this) \
W_RETURN(w_internal::binary::tree_append(STATE(w_counter.prev(), w_this), __VA_ARGS__))
#endif
Expand Down Expand Up @@ -733,7 +747,7 @@ template <typename... Args> constexpr QOverload<Args...> qOverload = {};
* or W_Access::Public (the default)
* - W_Compat: for deprecated methods (equivalent of Q_MOC_COMPAT)
*/
#define W_SLOT(...) W_SLOT2(__VA_ARGS__, w_internal::W_EmptyFlag)
#define W_SLOT(...) W_MACRO_MSVC_EXPAND(W_SLOT2(__VA_ARGS__, w_internal::W_EmptyFlag))
#define W_SLOT2(NAME, ...) \
W_STATE_APPEND(w_SlotState, w_internal::makeMetaSlotInfo( \
W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), #NAME, \
Expand All @@ -744,7 +758,7 @@ template <typename... Args> constexpr QOverload<Args...> qOverload = {};
* W_INVOKABLE( <slot name> [, (<parameters types>) ] [, <flags>]* )
* Exactly like W_SLOT but for Q_INVOKABLE methods.
*/
#define W_INVOKABLE(...) W_INVOKABLE2(__VA_ARGS__, w_internal::W_EmptyFlag)
#define W_INVOKABLE(...) W_MACRO_MSVC_EXPAND(W_INVOKABLE2(__VA_ARGS__, w_internal::W_EmptyFlag))
#define W_INVOKABLE2(NAME, ...) \
W_STATE_APPEND(w_MethodState, w_internal::makeMetaMethodInfo( \
W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME), #NAME, \
Expand All @@ -761,7 +775,7 @@ template <typename... Args> constexpr QOverload<Args...> qOverload = {};
* Like W_SLOT, there can be the types of the parametter as a second argument, within parentheses.
* You must then follow with the parameter names
*/
#define W_SIGNAL(...) W_SIGNAL2(__VA_ARGS__ , 0)
#define W_SIGNAL(...) W_MACRO_MSVC_EXPAND(W_SIGNAL2(__VA_ARGS__ , 0))
#define W_SIGNAL2(NAME, ...) \
{ /* W_SIGNAL need to be placed directly after the signal declaration, without semicolon. */\
using w_SignalType = decltype(W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME)); \
Expand All @@ -778,7 +792,7 @@ template <typename... Args> constexpr QOverload<Args...> qOverload = {};
/** \macro W_SIGNAL_COMPAT
* Same as W_SIGNAL, but set the W_Compat flag
*/
#define W_SIGNAL_COMPAT(...) W_SIGNAL_COMPAT2(__VA_ARGS__, 0)
#define W_SIGNAL_COMPAT(...) W_MACRO_MSVC_EXPAND(W_SIGNAL_COMPAT2(__VA_ARGS__, 0))
#define W_SIGNAL_COMPAT2(NAME, ...) \
{ \
using w_SignalType = decltype(W_OVERLOAD_RESOLVE(__VA_ARGS__)(&W_ThisType::NAME)); \
Expand Down Expand Up @@ -813,7 +827,7 @@ template <typename... Args> constexpr QOverload<Args...> qOverload = {};
*
* <type> can optionally be put in parentheses, if you have a type containing a comma
*/
#define W_PROPERTY(...) W_PROPERTY2(__VA_ARGS__) // expands the READ, WRITE, and other sub marcos
#define W_PROPERTY(...) W_MACRO_MSVC_EXPAND(W_PROPERTY2(__VA_ARGS__)) // expands the READ, WRITE, and other sub marcos
#define W_PROPERTY2(TYPE, NAME, ...) \
W_STATE_APPEND(w_PropertyState, \
w_internal::makeMetaPropertyInfo<W_MACRO_REMOVEPAREN(TYPE)>(\
Expand Down
13 changes: 9 additions & 4 deletions src/wobjectimpl.h
Original file line number Diff line number Diff line change
Expand Up @@ -488,12 +488,17 @@ template<std::size_t... S, std::size_t... I, std::size_t... O, std::size_t...N,
struct BuildStringDataHelper<std::index_sequence<S...>, std::index_sequence<I...>, std::index_sequence<O...>, std::index_sequence<N...>, T> {
using meta_stringdata_t = const qt_meta_stringdata_t<sizeof...(I), sizeof...(S)>;
static meta_stringdata_t qt_meta_stringdata;
#ifndef Q_CC_MSVC
static constexpr qptrdiff stringdata_offset = offsetof(meta_stringdata_t, stringdata);
#else // offsetof does not work with MSVC
static constexpr qptrdiff stringdata_offset = sizeof(meta_stringdata_t::data);
#endif
};
template<std::size_t... S, std::size_t... I, std::size_t... O, std::size_t...N, typename T>
const qt_meta_stringdata_t<sizeof...(I), sizeof...(S)>
BuildStringDataHelper<std::index_sequence<S...>, std::index_sequence<I...>, std::index_sequence<O...>, std::index_sequence<N...>, T>::qt_meta_stringdata = {
{Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(N-1,
qptrdiff(offsetof(meta_stringdata_t, stringdata) + O - I * sizeof(QByteArrayData)) )...},
stringdata_offset + O - I * sizeof(QByteArrayData))...},
{ concatenate(T::string_data)[S]... }
};

Expand Down Expand Up @@ -798,13 +803,13 @@ template<typename T, typename... Ts> auto qt_static_metacall_impl(Ts &&... args)
// So we need to work around that to extract the template stuff which may not exist or be composed
// of several macro arguments: If the first argument has parentheses, there must be at least two
// arguments, so just do a tail. Otherwise, there should be only one or two argument, so take the second.
#define W_MACRO_TEMPLATE_STUFF(...) W_MACRO_CONCAT(W_MACRO_TEMPLATE_STUFF_HELPER, W_MACRO_DELAY(W_MACRO_TEMPLATE_STUFF_QUERY,W_MACRO_TEMPLATE_STUFF_HELPER __VA_ARGS__)) (__VA_ARGS__)
#define W_MACRO_TEMPLATE_STUFF(...) W_MACRO_CONCAT(W_MACRO_TEMPLATE_STUFF_HELPER, W_MACRO_DELAY(W_MACRO_TEMPLATE_STUFF_QUERY,W_MACRO_TEMPLATE_STUFF_HELPER __VA_ARGS__))(__VA_ARGS__)
#define W_MACRO_TEMPLATE_STUFF_QUERY(...) W_MACRO_DELAY2(W_MACRO_FIRST, W_MACRO_TEMPLATE_STUFF_HELPER_ ## __VA_ARGS__)
#define W_MACRO_TEMPLATE_STUFF_HELPER(...) YES
#define W_MACRO_TEMPLATE_STUFF_HELPER_YES TAIL,
#define W_MACRO_TEMPLATE_STUFF_HELPER_W_MACRO_TEMPLATE_STUFF_HELPER SECOND,
#define W_MACRO_TEMPLATE_STUFF_HELPER_TAIL(X, ...) __VA_ARGS__
#define W_MACRO_TEMPLATE_STUFF_HELPER_SECOND(...) W_MACRO_TEMPLATE_STUFF_HELPER_SECOND2(__VA_ARGS__,,)
#define W_MACRO_TEMPLATE_STUFF_HELPER_TAIL(...) W_MACRO_MSVC_EXPAND(W_MACRO_TAIL(__VA_ARGS__))
#define W_MACRO_TEMPLATE_STUFF_HELPER_SECOND(...) W_MACRO_MSVC_EXPAND(W_MACRO_TEMPLATE_STUFF_HELPER_SECOND2(__VA_ARGS__,,))
#define W_MACRO_TEMPLATE_STUFF_HELPER_SECOND2(A,B,...) B
#define W_MACRO_FIRST_REMOVEPAREN(...) W_MACRO_REMOVEPAREN(W_MACRO_FIRST(__VA_ARGS__))

Expand Down

0 comments on commit 064747e

Please sign in to comment.