Remove __attribute__((...)) from a function pointer or reference - c++

#include <utility>
#include <iostream>
int main()
{
using std_type = std::remove_reference<void (__attribute__((stdcall)) &)(int) noexcept>::type;
using cdecl_type = std::remove_reference<void (__attribute__((cdecl)) &)(int) noexcept>::type;
using type = std::remove_reference<void (&)(int) noexcept>::type;
std::cout<<typeid(std_type).name()<<"\n";
std::cout<<typeid(cdecl_type).name()<<"\n";
std::cout<<typeid(type).name()<<"\n";
}
Output:
U7stdcallDoFviE
U5cdeclDoFviE
U5cdeclDoFviE
If I compare the types with std::is_same<std_type, cdecl_type>::value it returns false.
I need to remove the attribute so that the following code works, without having to have specializations for __stdcall:
template<typename T>
struct remove_class {};
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...)>
{
using type = R(A...);
};
template <typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const>
{
using type = R(A...);
};
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) volatile>
{
using type = R(A...);
};
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) noexcept>
{
using type = R(A...);
};
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const volatile>
{
using type = R(A...);
};
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const noexcept>
{
using type = R(A...);
};
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) volatile noexcept>
{
using type = R(A...);
};
template<typename C, typename R, typename... A>
struct remove_class<R(C::*)(A...) const volatile noexcept>
{
using type = R(A...);
};
template<typename T>
struct function_signature
{
using type = typename remove_class<decltype(&std::remove_reference<T>::type::operator())>::type;
};
template<typename R, typename... A>
struct function_signature<R(A...)>
{
using type = R(A...);
};
and:
template<typename T>
struct function_arguments_type
{
using type = typename function_arguments_type<typename function_signature<T>::type>::type;
};
template<typename R, typename... A>
struct function_arguments_type<R(A...)>
{
using type = typename std::tuple<A...>;
};
So that I can determine what is the return type of a function, and what is the type of its arguments.
Is there a way to remove the __attribute__((....)) from a function's signature or at least make my templates work without having to specialize every single one of them for __stdcall?

You can still create a traits remove_stdcall, something like:
template <typename Func>
struct remove_stdcall
{
using type = Func;
};
template <typename Ret, typename ... Args>
struct remove_stdcall<Ret __attribute__((stdcall)) (Args...) noexcept>
{
using type = Ret(Args...) noexcept;
};
template <typename Ret, typename ... Args>
struct remove_stdcall<Ret __attribute__((stdcall))(Args...)>
{
using type = Ret(Args...);
};
Demo.

Related

std::vector expansion parameters helper

I did not write this code, I hope everyone can help me.
I have the following code, which can reasonably expand the parameters of ordinary functions.
I hope it can, expand, the constructor of the class.
#include <iostream>
#include <utility>
#include <vector>
namespace util {
template <typename ReturnType, typename... Args>
struct function_traits_defs {
static constexpr size_t arity = sizeof...(Args);
using result_type = ReturnType;
template <size_t i>
struct arg {
using type = typename std::tuple_element<i, std::tuple<Args...>>::type;
};
};
template <typename T>
struct function_traits_impl;
template <typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(Args...)>
: function_traits_defs<ReturnType, Args...> {};
template <typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(*)(Args...)>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...)>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const&>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const&&>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile&>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) volatile&&>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile&>
: function_traits_defs<ReturnType, Args...> {};
template <typename ClassType, typename ReturnType, typename... Args>
struct function_traits_impl<ReturnType(ClassType::*)(Args...) const volatile&&>
: function_traits_defs<ReturnType, Args...> {};
template <typename T, typename V = void>
struct function_traits
: function_traits_impl<T> {};
template <typename T>
struct function_traits<T, decltype((void)&T::operator())>
: function_traits_impl<decltype(&T::operator())> {};
template <size_t... Indices>
struct indices {
using next = indices<Indices..., sizeof...(Indices)>;
};
template <size_t N>
struct build_indices {
using type = typename build_indices<N - 1>::type::next;
};
template <>
struct build_indices<0> {
using type = indices<>;
};
template <size_t N>
using BuildIndices = typename build_indices<N>::type;
namespace details {
template <typename FuncType,
typename VecType,
size_t... I,
typename Traits = function_traits<FuncType>,
typename ReturnT = typename Traits::result_type>
ReturnT do_call(FuncType& func, const VecType& args, indices<I...>) {
return func(args[I]...);
}
} // namespace details
template <typename FuncType, typename VecType, typename Traits = function_traits<FuncType>>
auto unpack_caller(FuncType& func, const VecType& args) {
return details::do_call(func, args, BuildIndices<Traits::arity>());
}
} // namespace util
int func(int a, int b, int c) {
return a + b + c;
}
int main() {
std::vector<int> args = {1, 2, 3};
int j = util::unpack_caller(func, args);
std::cout << j << std::endl;
return 0;
}
e.g By adding a class function in the form of a template, and automatically looking for the parameters of the constructor.
class foo
{
public:
foo(uint32_t a, uint32_t b, uint32_t c){};
};
int main() {
std::vector<int> args1 = {1, 2, 3};
foo* f = util::unpack_caller<foo>(args);
return 0;
}
This first argument of the unpack_caller method should be a callable object, but the constructor of a class is not a callable object. So, you can put a factory method inside your class and do like this:
class foo
{
public:
foo(uint32_t a, uint32_t b, uint32_t c) {};
static foo* getInstnce(uint32_t a, uint32_t b, uint32_t c)
{
return new foo(a,b,c);
}
};
int main() {
std::vector<int> args1 = { 1, 2, 3 };
foo* f = util::unpack_caller(foo::getInstnce, args1);
return 0;
}

Resolving to different types based on the argument types of a c++ template function

I'm doing some metaprogramming and I have ran into the following problem:
I have a class that takes one template parameter T, T can be assumed to be a function with an arbitary signature. The class a member variable V, that should have the type std::tuple<> if T takes no arguments or the first argument is not a std::tuple. If the first argument is an std::tuple, V should instead have the same type as first argument.
Example:
void f() // Should resolve to std::tuple<>
void f(int) // Should resolve to std::tuple<>
void f(std::tuple<int, float>) // Should resolve to std::tuple<int, float>
void f(std::tuple<float>, int) // Should resolve to std::tuple<float>
I have been trying something similar to this, but with no success. As it fails when indexing the first arguement on the argument free function, without selecting any of the other alternatives in spite of those being available. I'm using MSVC 2019 16.8.4
#include <functional>
#include <concepts>
namespace detail
{
template<typename... ArgTs>
struct HasArgs : public std::conditional<(sizeof... (ArgTs) > 0), std::true_type, std::false_type>::type {};
}
//!
//! Provides argument function information
//! Based on: https://stackoverflow.com/a/9065203
//!
template<typename T>
class FunctionTraits;
template<typename R, typename... Args>
class FunctionTraits<R(Args...)>
{
public:
static const size_t arg_count = sizeof...(Args);
using HasArguments = detail::HasArgs<Args...>;
using ReturnType = R;
using ArgTypes = std::tuple<Args...>;
template <size_t i>
struct arg
{
using type = typename std::tuple_element<i, std::tuple<Args...>>::type;
};
};
namespace detail
{
template <typename T>
struct is_tuple : std::false_type {};
template <typename... Args>
struct is_tuple<std::tuple<Args...>>: std::true_type {};
}
template <typename T>
concept is_tuple = requires() { detail::is_tuple<T>::value; };
class TestMemberFunctions
{
public:
static int test_f1(std::tuple<int, float>, int)
{
return 0;
}
static int test_f2(int)
{
return 0;
}
static int test_f3()
{
return 0;
}
};
template <typename CreateT> requires (!FunctionTraits<CreateT>::HasArguments::value)
std::tuple<> TypeDeductionDummyFunction();
template <typename CreateT> requires FunctionTraits<CreateT>::HasArguments::value
auto TypeDeductionDummyFunction() -> std::conditional<is_tuple<typename FunctionTraits<CreateT>::template arg<0>::type>,
typename FunctionTraits<CreateT>::template arg<0>::type,
std::tuple<>>;
template <typename T>
class SampleClass
{
decltype(TypeDeductionDummyFunction<T>()) m_member;
};
SampleClass<decltype(TestMemberFunctions::test_f1)> c1;
SampleClass<decltype(TestMemberFunctions::test_f2)> c2;
SampleClass<decltype(TestMemberFunctions::test_f3)> c3;
Something along these lines, perhaps:
template <typename T> struct ExtractFirstTuple;
template <typename R>
struct ExtractFirstTuple<R()> {
using type = std::tuple<>;
};
template <typename R, typename... Ts, typename... Args>
struct ExtractFirstTuple<R(std::tuple<Ts...>, Args...)> {
using type = std::tuple<Ts...>;
};
template <typename R, typename First, typename... Args>
struct ExtractFirstTuple<R(First, Args...)> {
using type = std::tuple<>;
};
Demo
An attempt to build what you want from more primitive operations.
template<typename T, std::size_t N>
struct FunctionArgument {
static constexpr bool exists = false;
};
template<typename R, typename A0, typename... Args>
struct FunctionArgument<R(A0, Args...), 0>{
using type=A0;
static constexpr bool exists = true;
};
template<typename R, typename A0, typename... Args, std::size_t N>
struct FunctionArgument<R(A0, Args...), N>:
FunctionArgument<R(Args...), N-1>
{};
template<class Sig, std::size_t N>
using FuncArg_type = typename FunctionArgument<Sig, N>::type;
template<class Sig, std::size_t N>
constexpr bool FuncArg_exists = FunctionArgument<Sig, N>::exists;
template<class Sig, class Otherwise>
using FirstArgIfExists =
typename std::conditional_t<
FuncArg_exists<Sig,0>,
FunctionArgument<Sig, 0>,
std::type_identity<Otherwise>
>::type;
template<class T, class Otherwise>
struct TypeIfTuple {
using type=Otherwise;
};
template<class...Ts, class Otherwise>
struct TypeIfTuple<std::tuple<Ts...>, Otherwise> {
using type=std::tuple<Ts...>;
};
template<class T, class Otherwise>
using TypeIfTuple_t = typename TypeIfTuple<T,Otherwise>::type;
template<class Sig>
using TheTypeYouWant = TypeIfTuple_t<
FirstArgIfExists<Sig, std::tuple<>>,
std::tuple<>
>;

Accessing the return type of a method

I'm having a hard time getting this simple thing going.
One thing I found that works:
#include <type_traits>
struct A
{
int Method();
};
static_assert( std::is_same_v<
decltype(A{}.Method()), int
>
); // pass. cool.
Ok great. But no; not great. Because I now have a default constructible requirement, AND I need to write a call expression with all arguments. And who knows about them !
Consider the real situation:
struct A
{
int Method(MysteriousArgumentsIDontCareAboutAndCanChangeInTheFuture);
};
static_assert( std::is_same_v<
decltype(A{}.Method()), int
>
); // not so cool anymore (too few arguments to function call, expected 1, have 0)
How about using std::invoke_result ?
static_assert( std::is_same_v<
std::invoke_result_t< A::Method >, int
>
);
nah.
call to non-static member function without an object argument
MSVC says
non-standard syntax; use '&' to create a pointer to member
I can fiddle all I want with this expression, nothing good comes out of it.
e.g.:
using T = std::invoke_result_t< decltype(&A::Method) >;
error: no type named 'type' in 'std::invoke_result
If I remove the decltype it's type-value mismatch (of course) etc...
cppreference.com mentions this usage for the C++14 version:
std::result_of<decltype(&C::Func)(C, char, int&)>::type
Not much better than my first attempt. All the arguments are still there.
In action in our simple case: https://godbolt.org/z/KtQbth
Help ?
You can use the trait suggested by Piotr Skotnicki:
template <typename T>
struct return_type;
template <typename R, typename... Args>
struct return_type<R(Args...)> { using type = R; };
template <typename R, typename... Args>
struct return_type<R(*)(Args...)> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...)> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) &> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) &&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const&&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) volatile> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) volatile&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) volatile&&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const volatile> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const volatile&> { using type = R; };
template <typename R, typename C, typename... Args>
struct return_type<R(C::*)(Args...) const volatile&&> { using type = R; };
template <typename T>
using return_type_t = typename return_type<T>::type;
Now you can do:
static_assert(std::is_same_v<return_type_t<decltype(&A::Method)>, int>);
[static_assert( std::is_same_v< decltype(std::declval<A>().Method()), int >);//super cool now][1]

std::is_detected in MSVC does not work with templates

I implemented std::experimental::is_detected from both https://en.cppreference.com/w/cpp/experimental/is_detected as well as Strange MSVC behaviour with std::experimental::is_detected to be sure that nothing is going on there.
However from what I see is_detected does not seem to work for template classes in MSVC while it is fine on both Clang and GCC. Any ideas on how to make this work in MSVC?
The full reproduction code is also over at
https://godbolt.org/z/wYe9M3
#include <type_traits>
// Type representing a missing type.
struct nonesuch
{
nonesuch() = delete;
~nonesuch() = delete;
nonesuch(nonesuch const&) = delete;
void operator=(nonesuch const&) = delete;
};
#if 1 // from cppreference
namespace detail {
template <class Default, class AlwaysVoid,
template<class...> class Op, class... Args>
struct detector {
using value_t = std::false_type;
using type = Default;
};
template <class Default, template<class...> class Op, class... Args>
struct detector<Default, std::void_t<Op<Args...>>, Op, Args...> {
// Note that std::void_t is a C++17 feature
using value_t = std::true_type;
using type = Op<Args...>;
};
} // namespace detail
template <template<class...> class Op, class... Args>
using is_detected = typename detail::detector<nonesuch, void, Op, Args...>::value_t;
template <template<class...> class Op, class... Args>
using detected_t = typename detail::detector<nonesuch, void, Op, Args...>::type;
#else
namespace internal
{
template <typename V, typename D>
struct detect_impl
{
using value_t = V;
using type = D;
};
template <typename D, template <typename...> class Check, typename... Args>
auto detect_check(char)
-> detect_impl<std::false_type, D>;
template <typename D, template <typename...> class Check, typename... Args>
auto detect_check(int)
-> decltype(std::void_t<Check<Args...>>(),
detect_impl<std::true_type, Check<Args...>>{});
template <typename D, typename Void, template <typename...> class Check, typename... Args>
struct detect : decltype(detect_check<D, Check, Args...>(0)) {};
}
template <template< typename... > class Check, typename... Args>
using is_detected = typename internal::detect<nonesuch, void, Check, Args...>::value_t;
#endif
template <typename T, typename ...Ts>
using foo_bar = decltype(std::declval<T>().bar(std::declval<Ts>()...));
template <typename T>
using has_bar = is_detected<foo_bar, T, int>;
template<class T>
struct InterfaceImpl
{
static constexpr bool val = has_bar<T>::value;
protected:
int bar(int t) const {return 2;}
};
struct S : public InterfaceImpl<S> {};
struct S2 : public InterfaceImpl<S2>
{
int bar(int t) const {return 3;}
};
struct NonTemplate{};
struct NonTemplate2{
int bar(int t) const {return 3;}
};
int main(void)
{
S s;
static_assert(s.val == false);
S2 s2;
static_assert(s2.val == true);
static_assert(has_bar<NonTemplate>::value == false);
static_assert(has_bar<NonTemplate2>::value == true);
return 0;
}

Template parameter - function pointer with variadic arguments

I know I can do this:
template<typename T, typename Ret, typename A1, typename A2, Ret(T::*F)(A1, A2)>
class C{}
But as you can see this A1 and A2 are bit ugly. In fact I don't know the number of arguments. Sounds like a work for variadic templates. Unfortunately I can't do this:
// doesn't work - parameter pack must appear at the end of the template parameter list
template<typename T, typename Ret, typename... Args, Ret(T::*F)(Args...)>
class C{}
Nor this:
template
class C;
// doesn't work - wrong syntax
template<typename T, typename F, typename Ret, typename... Args>
class Delegate2<Ret(T::*F)(Args...)>{}
Do I want too much?
You could do the following:
template<typename T, T> struct C;
template<typename T, typename R, typename ...Args, R (T::*F)(Args...)>
struct C<R (T::*)(Args...), F> {
R operator()(T &obj, Args &&... args) {
return (obj.*F)(std::forward<Args>(args)...);
}
};
and then in your program:
struct A {
int foo(int i) { return i; }
};
int main() {
C<int(A::*)(int), &A::foo> c;
A a;
std::cout << c(a, 42) << std::endl;
}
Live Demo
template<class T>struct tag{using type=T;};
template<class Tag>using type=typename Tag::type;
template<class T, class Sig>
struct member_function_pointer;
template<class T, class Sig>
using member_function_pointer_t=type<member_function_pointer<T,Sig>>;
template<class T, class R, class...Args>
struct member_function_pointer<T, R(Args...)>:
tag<R(T::*)(Args...)>
{};
then
template<class T, class Sig, member_function_pointer_t<T,Sig> mf>
class C{};
should do the trick. If you need access to Args..., you can specialize.
template<class T, class Sig, member_function_pointer_t<T,Sig> mf>
class C;
template<class T, class R, class...Args, member_function_pointer_t<T,R(Args...)> mf>
class C<T, R(Args...), mf> {
};
like that.