Skip to content

Commit

Permalink
Merge pull request #16 from pfultz2/msvc-alias
Browse files Browse the repository at this point in the history
Msvc alias
  • Loading branch information
pfultz2 committed Aug 11, 2015
2 parents 0c0c5dd + 6edb331 commit 1d4aa72
Show file tree
Hide file tree
Showing 30 changed files with 671 additions and 386 deletions.
1 change: 1 addition & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,7 @@ add_test_executable(compose)
add_test_executable(compress)
add_test_executable(conditional)
add_test_executable(construct)
add_test_executable(filter)
add_test_executable(fix)
add_test_executable(flip)
add_test_executable(flow)
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@

os: Visual Studio 2015 RC
os: Visual Studio 2015

environment:
matrix:
Expand Down
165 changes: 165 additions & 0 deletions fit/alias.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,165 @@
/*=============================================================================
Copyright (c) 2015 Paul Fultz II
alias.h
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
==============================================================================*/

#ifndef FIT_GUARD_ALIAS_H
#define FIT_GUARD_ALIAS_H

#include <fit/returns.h>
#include <fit/detail/delegate.h>
#include <fit/detail/move.h>
#include <fit/detail/holder.h>

/// alias
/// =====
///
/// Description
/// -----------
///
/// The `alias` class wraps a type with a new type that can be tagged by the
/// user.
///
/// Synopsis
/// --------
///
/// // Alias the type using a member variable
/// template<class T, class Tag=void>
/// class alias;
///
/// // Alias the type by inheriting
/// template<class T, class Tag=void>
/// class alias_inherit;
///
/// // Alias the type using a static variable
/// template<class T, class Tag=void>
/// class alias_static;
///
/// // Retrieve tag from alias
/// template<class Alias>
/// class alias_tag;
///
/// // Check if type has a certian tag
/// template<class T, class Tag>
/// class has_tag;
///
/// // Retrieve value from alias
/// template<class Alias>
/// constexpr auto alias_value(Alias&&);
///

namespace fit {

template<class T>
struct alias_tag;

template<class T, class Tag, class=void>
struct has_tag
: std::false_type
{};

template<class T, class Tag>
struct has_tag<T, Tag, typename detail::holder<
typename alias_tag<T>::type
>::type>
: std::is_same<typename alias_tag<T>::type, Tag>
{};

namespace detail {

template<class T>
constexpr T& lvalue(T& x)
{
return x;
}

template<class T>
constexpr const T& lvalue(const T& x)
{
return x;
}

}

#define FIT_UNARY_PERFECT_ID(...) __VA_ARGS__
#define FIT_UNARY_PERFECT_FOREACH(m) \
m(const&, fit::detail::lvalue) \
m(&, fit::detail::lvalue) \
m(&&, fit::move) \

template<class T, class Tag=void>
struct alias
{
T value;
FIT_DELGATE_CONSTRUCTOR(alias, T, value)
};

#define FIT_DETAIL_ALIAS_GET_VALUE(ref, move) \
template<class T, class Tag, class... Ts> \
constexpr auto alias_value(alias<T, Tag> ref a, Ts&&...) FIT_RETURNS(move(a.value))
FIT_UNARY_PERFECT_FOREACH(FIT_DETAIL_ALIAS_GET_VALUE)

template<class T, class Tag>
struct alias_tag<alias<T, Tag>>
{ typedef Tag type; };


template<class T, class Tag=void>
struct alias_inherit
#if (defined(__GNUC__) && !defined (__clang__))
: std::conditional<(std::is_class<T>::value), T, alias<T>>::type
#else
: T
#endif
{
FIT_INHERIT_CONSTRUCTOR(alias_inherit, T)
};

#define FIT_DETAIL_ALIAS_INHERIT_GET_VALUE(ref, move) \
template<class T, class Tag, class... Ts, class=typename std::enable_if<(std::is_class<T>::value)>::type> \
constexpr T ref alias_value(alias_inherit<T, Tag> ref a, Ts&&...) \
{ \
return move(a); \
}
FIT_UNARY_PERFECT_FOREACH(FIT_DETAIL_ALIAS_INHERIT_GET_VALUE)

template<class T, class Tag>
struct alias_tag<alias_inherit<T, Tag>>
{ typedef Tag type; };

namespace detail {

template<class T, class Tag>
struct alias_static_storage
{
static constexpr T value = T();
};

template<class T, class Tag>
constexpr T alias_static_storage<T, Tag>::value;

}

template<class T, class Tag=void>
struct alias_static
{
template<class... Ts, FIT_ENABLE_IF_CONSTRUCTIBLE(T, Ts...)>
constexpr alias_static(Ts&&...)
{}
};

template<class T, class Tag, class... Ts>
constexpr const T& alias_value(const alias_static<T, Tag>&, Ts&&...)
{
return detail::alias_static_storage<T, Tag>::value;
}

template<class T, class Tag>
struct alias_tag<alias_static<T, Tag>>
{ typedef Tag type; };

}

#endif
2 changes: 1 addition & 1 deletion fit/args.h
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ template<class T, T N>
struct args_f
{
template<class... Ts>
constexpr auto operator()(Ts&&... xs) FIT_RETURNS
constexpr auto operator()(Ts&&... xs) const FIT_RETURNS
(
get_args<N>(fit::forward<Ts>(xs)...)
);
Expand Down
4 changes: 2 additions & 2 deletions fit/combine.h
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ struct combine_adaptor_base<seq<Ns...>, F, Gs...>

FIT_RETURNS_CLASS(combine_adaptor_base);

// Result needs to be calulated in a seperate class to avoid confusing the
// Result needs to be calculated in a separate class to avoid confusing the
// compiler on MSVC
#if FIT_NO_EXPRESSION_SFINAE || FIT_HAS_MANUAL_DEDUCTION
template<class... Ts>
Expand All @@ -93,7 +93,7 @@ struct combine_adaptor_base<seq<Ns...>, F, Gs...>
operator()(Ts&&... xs) const FIT_SFINAE_MANUAL_RETURNS
(
(FIT_MANGLE_CAST(const F&)(FIT_CONST_THIS->base_function(xs...)))
(pack_get<Ns, Gs, pack_tag<Gs...>>(*FIT_CONST_THIS, xs)(fit::forward<Ts>(xs))...)
(alias_value<Gs, pack_tag<seq<Ns>, Gs...>>(*FIT_CONST_THIS, xs)(fit::forward<Ts>(xs))...)
);
};

Expand Down
6 changes: 6 additions & 0 deletions fit/conditional.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,12 @@ struct conditional_adaptor
: base(fit::forward<X>(f1), kernel_base(fit::forward<Xs>(fs)...))
{}

template<class X, class... Xs,
FIT_ENABLE_IF_CONSTRUCTIBLE(base, X)>
constexpr conditional_adaptor(X&& f1)
: base(fit::forward<X>(f1))
{}

struct failure
: failure_for<F, Fs...>
{};
Expand Down

0 comments on commit 1d4aa72

Please sign in to comment.