preliminary support for calling conventions

This commit is contained in:
badair
2016-04-08 07:22:55 -05:00
parent f1888031c7
commit 42e5ef079e
10 changed files with 363 additions and 18 deletions

View File

@@ -0,0 +1,34 @@
/*!<-
Copyright (c) 2016 Barrett Adair
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
->*/
//[ calling_convention_cdecl
#define CALLABLE_TRAITS_ENABLE_CDECL
#include <type_traits>
#include <callable_traits/has_calling_convention.hpp>
#include <callable_traits/add_calling_convention.hpp>
namespace ct = callable_traits;
namespace cc = callable_traits::calling_conventions;
struct foo {};
int main() {
using pmf = void(foo::*)();
using pmf_cdecl = void(__cdecl foo::*)();
static_assert(!std::is_same<pmf, pmf_cdecl>::value, "");
static_assert(!ct::has_calling_convention<pmf, cc::cdecl>(), "");
static_assert(ct::has_calling_convention<pmf_cdecl, cc::cdecl>(), "");
using test = ct::add_calling_convention<pmf, cc::cdecl>;
static_assert(std::is_same<test, pmf_cdecl>::value, "");
static_assert(ct::has_calling_convention<test, cc::cdecl>(), "");
}
//]

View File

@@ -0,0 +1,111 @@
/*!
@file add_function_const
@copyright Barrett Adair 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef CALLABLE_TRAITS_ADD_CALLING_CONVENTION_HPP
#define CALLABLE_TRAITS_ADD_CALLING_CONVENTION_HPP
#include <callable_traits/detail/calling_conventions.hpp>
#include <callable_traits/detail/required_definitions.hpp>
namespace callable_traits {
namespace detail {
template<bool Sfinae, typename Tag>
struct add_calling_convention_error {
static_assert(Sfinae,
"Unknown calling convention type. Did you use a type "
"from namespace callable_traits::calling_conventions?");
};
template<bool Sfinae>
struct add_calling_convention_error<Sfinae, calling_conventions::stdcall> {
#ifdef CALLABLE_TRAITS_ENABLE_STDCALL
static_assert(Sfinae,
"Unable to add __stdcall to type T in "
"callable_traits::add_calling_convention<T, "
"callable_traits::calling_conventions::stdcall>.");
#else
static_assert(Sfinae,
"__stdcall functionality not enabled. Define "
"CALLABLE_TRAITS_ENABLE_STDCALL to enable.");
#endif
};
template<bool Sfinae>
struct add_calling_convention_error<Sfinae, calling_conventions::fastcall> {
#ifdef CALLABLE_TRAITS_ENABLE_FASTCALL
static_assert(Sfinae,
"Unable to add __fastcall to type T in "
"callable_traits::add_calling_convention<T, "
"callable_traits::calling_conventions::fastcall>.");
#else
static_assert(Sfinae,
"__fastcall functionality not enabled. Define "
"CALLABLE_TRAITS_ENABLE_FASTCALL to enable.");
#endif
};
template<bool Sfinae>
struct add_calling_convention_error<Sfinae, calling_conventions::cdecl> {
#ifdef CALLABLE_TRAITS_ENABLE_CDECL
static_assert(Sfinae,
"Unable to add __cdecl to type T in "
"callable_traits::add_calling_convention<T, "
"callable_traits::calling_conventions::cdecl>.");
#else
static_assert(Sfinae,
"__cdecl functionality not enabled. Define "
"CALLABLE_TRAITS_ENABLE_CDECL to enable.");
#endif
};
template<bool Sfinae>
struct add_calling_convention_error<Sfinae, calling_conventions::pascal> {
#ifdef CALLABLE_TRAITS_ENABLE_PASCAL
static_assert(Sfinae,
"Unable to add pascal to type T in "
"callable_traits::add_calling_convention<T, "
"callable_traits::calling_conventions::pascal>.");
#else
static_assert(Sfinae,
"pascal functionality not enabled. Define "
"CALLABLE_TRAITS_ENABLE_PASCAL to enable.");
#endif
};
}
namespace permissive {
template<typename T, typename Tag>
using add_calling_convention = detail::fallback_if_invalid<
typename detail::add_calling_convention_t<T, Tag>::type,
T>;
}
namespace verbose {
template<typename T, typename Tag>
using add_calling_convention = detail::fail_if_invalid<
typename detail::add_calling_convention_t<T, Tag>::type,
detail::add_calling_convention_error<false, Tag>>;
}
template<typename T, typename Tag>
using add_calling_convention = detail::fail_if_invalid<
typename detail::add_calling_convention_t<T, Tag>::type,
detail::add_calling_convention_error<true, Tag>>;
}
#endif //CALLABLE_TRAITS_ADD_CALLING_CONVENTION_HPP

View File

@@ -44,6 +44,8 @@ Distributed under the Boost Software License, Version 1.0.
#include <callable_traits/remove_function_reference.hpp>
#include <callable_traits/remove_varargs.hpp>
#include <callable_traits/remove_function_volatile.hpp>
#include <callable_traits/has_calling_convention.hpp>
#include <callable_traits/add_calling_convention.hpp>
#include <callable_traits/result_of.hpp>
#endif

View File

@@ -0,0 +1,98 @@
/*
Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
Copyright (c) 2016 Modified Work Barrett Adair
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef CALLABLE_TRAITS_DETAIL_CALLING_CONVENTIONS_HPP
#define CALLABLE_TRAITS_DETAIL_CALLING_CONVENTIONS_HPP
#include <callable_traits/detail/utility.hpp>
#include <tuple>
namespace callable_traits {
namespace calling_conventions {
struct cdecl{};
struct stdcall{};
struct fastcall{};
struct pascal{};
}
namespace detail {
template<typename T, typename Tag>
struct add_calling_convention_t {
using type = invalid_type;
};
template<typename T, typename Tag>
struct has_calling_convention_t {
using type = std::false_type;
};
// function pointers
#ifdef CALLABLE_TRAITS_ENABLE_STDCALL
#define CALLABLE_TRAITS_CC_TAG calling_conventions::stdcall
#define CALLABLE_TRAITS_CC __stdcall
#define CALLABLE_TRAITS_ST
#include <callable_traits/detail/function_cc.hpp>
#undef CALLABLE_TRAITS_CC
#undef CALLABLE_TRAITS_ST
#undef CALLABLE_TRAITS_CC_TAG
#endif
#ifdef CALLABLE_TRAITS_ENABLE_FASTCALL
#define CALLABLE_TRAITS_CC_TAG calling_conventions::fastcall
#define CALLABLE_TRAITS_CC __fastcall
#define CALLABLE_TRAITS_ST
#include <callable_traits/detail/function_cc.hpp>
#undef CALLABLE_TRAITS_CC
#undef CALLABLE_TRAITS_ST
#undef CALLABLE_TRAITS_CC_TAG
#endif
#ifdef CALLABLE_TRAITS_ENABLE_PASCAL
#define CALLABLE_TRAITS_CC_TAG calling_conventions::pascal
#define CALLABLE_TRAITS_CC
#define CALLABLE_TRAITS_ST pascal
#include <callable_traits/detail/function_cc.hpp>
#undef CALLABLE_TRAITS_CC
#undef CALLABLE_TRAITS_ST
#undef CALLABLE_TRAITS_CC_TAG
#endif
// member function pointers
#ifdef CALLABLE_TRAITS_ENABLE_CDECL
#define CALLABLE_TRAITS_CC_TAG calling_conventions::cdecl
#define CALLABLE_TRAITS_CC __cdecl
#include <callable_traits/detail/pmf_cc.hpp>
#undef CALLABLE_TRAITS_CC
#undef CALLABLE_TRAITS_CC_TAG
#endif
#ifdef CALLABLE_TRAITS_ENABLE_STDCALL
#define CALLABLE_TRAITS_CC_TAG calling_conventions::stdcall
#define CALLABLE_TRAITS_CC __stdcall
#include <callable_traits/detail/pmf_cc.hpp>
#undef CALLABLE_TRAITS_CC
#undef CALLABLE_TRAITS_CC_TAG
#endif
#ifdef CALLABLE_TRAITS_ENABLE_FASTCALL
#define CALLABLE_TRAITS_CC_TAG calling_conventions::fastcall
#define CALLABLE_TRAITS_CC __fastcall
#include <callable_traits/detail/pmf_cc.hpp>
#undef CALLABLE_TRAITS_CC
#undef CALLABLE_TRAITS_CC_TAG
#endif
}
}
#endif

View File

@@ -129,6 +129,7 @@ struct function<Return (Args..., ...) QUAL>
using apply_return = NewReturn(Args..., ...) QUAL; \
} \
/**/
namespace callable_traits {
namespace detail {

View File

@@ -0,0 +1,34 @@
/*
Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
Copyright (c) 2016 Modified Work Barrett Adair
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
DO NOT INCLUDE THIS HEADER DIRECTLY
*/
template<typename Ret, typename... Args>
struct add_calling_convention_t<
Ret(*)(Args...), CALLABLE_TRAITS_CC_TAG> {
using type = CALLABLE_TRAITS_ST Ret(CALLABLE_TRAITS_CC*)(Args...);
};
template<typename Ret, typename... Args>
struct add_calling_convention_t<
Ret(*)(Args..., ...), CALLABLE_TRAITS_CC_TAG> {
using type = CALLABLE_TRAITS_ST Ret(CALLABLE_TRAITS_CC*)(Args..., ...);
};
template<typename Ret, typename... Args>
struct has_calling_convention_t<
CALLABLE_TRAITS_ST Ret(CALLABLE_TRAITS_CC*)(Args...), CALLABLE_TRAITS_CC_TAG> {
using type = std::true_type;
};
template<typename Ret, typename... Args>
struct has_calling_convention_t<
CALLABLE_TRAITS_ST Ret(CALLABLE_TRAITS_CC*)(Args..., ...), CALLABLE_TRAITS_CC_TAG> {
using type = std::true_type;
};

View File

@@ -0,0 +1,52 @@
/*
Copyright (c) 2001 Peter Dimov and Multi Media Ltd.
Copyright (c) 2016 Modified Work Barrett Adair
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
DO NOT INCLUDE THIS HEADER DIRECTLY
*/
#define CALLABLE_TRAITS_SPECIALIZE_PMF_CC(QUAL) \
\
template<typename Ret, typename T, typename... Args> \
struct add_calling_convention_t< \
Ret(T::*)(Args...) QUAL, CALLABLE_TRAITS_CC_TAG> { \
using type = Ret(CALLABLE_TRAITS_CC T::*)(Args...); \
}; \
\
template<typename Ret, typename T, typename... Args> \
struct add_calling_convention_t< \
Ret(T::*)(Args..., ...) QUAL, CALLABLE_TRAITS_CC_TAG> { \
using type = Ret(CALLABLE_TRAITS_CC T::*)(Args..., ...); \
}; \
\
template<typename Ret, typename T, typename... Args> \
struct has_calling_convention_t< \
Ret(CALLABLE_TRAITS_CC T::*)(Args...) QUAL, CALLABLE_TRAITS_CC_TAG> { \
using type = std::true_type; \
}; \
\
template<typename Ret, typename T, typename... Args> \
struct has_calling_convention_t< \
Ret(CALLABLE_TRAITS_CC T::*)(Args..., ...) QUAL, CALLABLE_TRAITS_CC_TAG> { \
using type = std::true_type; \
} \
/**/
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(CALLABLE_TRAITS_EMPTY);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(&);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(&&);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(const);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(volatile);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(const volatile);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(const &);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(volatile &);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(const volatile &);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(const &&);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(volatile &&);
CALLABLE_TRAITS_SPECIALIZE_PMF_CC(const volatile &&);
#undef CALLABLE_TRAITS_SPECIALIZE_PMF_CC

View File

@@ -24,6 +24,7 @@ struct constants {
struct invalid_type { invalid_type() = delete; };
namespace detail {
// used to convey "this type doesn't matter" in code

View File

@@ -0,0 +1,25 @@
/*!
@file add_function_const
@copyright Barrett Adair 2015
Distributed under the Boost Software License, Version 1.0.
(See accompanying file LICENSE.md or copy at http://boost.org/LICENSE_1_0.txt)
*/
#ifndef CALLABLE_TRAITS_HAS_CALLING_CONVENTION_HPP
#define CALLABLE_TRAITS_HAS_CALLING_CONVENTION_HPP
#include <callable_traits/detail/calling_conventions.hpp>
#include <callable_traits/detail/required_definitions.hpp>
namespace callable_traits {
template<typename T, typename Tag>
inline constexpr auto
has_calling_convention() {
return typename detail::has_calling_convention_t<T, Tag>::type{};
}
}
#endif //CALLABLE_TRAITS_HAS_CALLING_CONVENTION_HPP

View File

@@ -7,30 +7,17 @@ Distributed under the Boost Software License, Version 1.0.
//[ result_of
#include <type_traits>
#include <callable_traits/callable_traits.hpp>
#define CALLABLE_TRAITS_ENABLE_CDECL
#include <callable_traits/add_calling_convention.hpp>
namespace ct = callable_traits;
using expect = int;
struct foo;
template<typename T>
void test() {
using result = ct::result_of<T>;
static_assert(std::is_same<expect, result>{}, "");
}
int main() {
test<int()>();
test<int(*)()>();
test<int(&)()>();
test<int() const>();
test<int(foo::*)() const>();
auto x = []() -> int { return 0; };
test<decltype(x)>();
using pmf = void(foo::*)();
using expect = void(__cdecl foo::*)();
static_assert(!std::is_same<pmf, expect>::value, "");
}
//]