Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to create a trait to answer if a type comes from std?

After this question by utilizing ADL one can create a trait to answer if the passed type comes from our namespace:

#include <utility>

namespace helper
{
  template <typename T, typename = void>
  struct is_member_of_sample : std::false_type
  {
  };

  template <typename T>
  struct is_member_of_sample<
      T,
      decltype(adl_is_member_of_sample(std::declval<T>()))> : std::true_type
  {
  };
}

namespace sample
{
  template <typename T>
  auto adl_is_member_of_sample(T && ) -> void;
}

// -- Test it

namespace sample
{
  struct X;
}

struct Y;

static_assert(helper::is_member_of_sample<sample::X>::value, "");
static_assert(not helper::is_member_of_sample<Y>::value, "");

int main(){}

From obvious reason this cannot be applied to the std namespace - there is simply no way to inject the adl_is_member_of_sample equivalent to the std namespace without exposing ourself to undefined behaviour.

Is there some workaround enabling to create the trait?

like image 434
W.F. Avatar asked Feb 04 '17 16:02

W.F.


1 Answers

This seems to work:

#include <functional>
#include <type_traits>
#include <utility>
#include <string>

namespace other { struct S{}; }

namespace my {
    template< class Type >
    void ref( Type&& ) {}

    template< class Type >
    auto ref_to( Type&& o )
        -> Type&
    { return o; }

    template< class Type >
    constexpr auto is_std_type()
        -> bool
    {
        using std::is_same;
        using std::declval;
        return not is_same< void, decltype( ref( ref_to( declval<Type>() ) ) )>::value;
    }

    struct Blah {};

    constexpr bool int_is_std       = is_std_type<int>();
    constexpr bool blah_is_std      = is_std_type<Blah>();
    constexpr bool other_is_std     = is_std_type<other::S>();
    constexpr bool string_is_std    = is_std_type<std::string>();
};

#include <iostream>
using namespace std;
auto main()
    -> int
{
    cout << boolalpha;
    cout << "int is std = " << my::int_is_std << "\n";
    cout << "blah is std = " << my::blah_is_std << "\n";
    cout << "other is std = " << my::other_is_std << "\n";
    cout << "string is std = " << my::string_is_std << "\n";
}
like image 173
Cheers and hth. - Alf Avatar answered Nov 22 '22 09:11

Cheers and hth. - Alf