2

p0887r1:

2.3 Fundamental metafunction building block

There are two ubiquitous idioms for type traits:

  • define a public data member value with a given value
  • define a public member typedef type that names a given type

It is surprising that there is a standard utility providing the former (std::integral_constant), but no standard utility providing the latter. type_identity is this utility. It is a fundamental building block that other metafunctions can simply inherit from. For example, remove_const could be implemented as follows:

template <typename T>
struct remove_const : type_identity<T> {};
template <typename T>
struct remove_const<T const> : type_identity<T> {};

Its implementation is simple:

template<class T>
struct type_identity
{
    using type = T;
};

So, I try to use type_identity widely in my codes, including personal implementation of Detection Idiom:

namespace detail
{
    template<class Default,
        class AlwaysVoid,
        template<class...>
        class Op,
        class... Args>
    struct detector : type_identity<Default>                                                           // here
    {
        using value_t = std::false_type;
    };    
    template<class Default, template<class...> class Op, class... Args>
    struct detector<Default, std::void_t<Op<Args...>>, Op, Args...>
        : type_identity<Op<Args...>>                                                                           // here
    {
        using value_t = std::true_type;
    };    
} // namespace detail
// ......

It works fine everywhere until I used libcxx's testsuits for my own implementation of is_destructible, below is the failure case:

struct ProtectedDestructor
{
protected:
    ~ProtectedDestructor()
    {}
};
// ......
template<class T>
void
test_is_not_destructible()
{
    static_assert(!is_destructible<T>::value, "");
    // ......
}
// ......
test_is_not_destructible<ProtectedDestructor>();

live demo:

prog.cc:83:47: error: '~ProtectedDestructor' is a protected member of 'ProtectedDestructor'

using has_dtor = decltype(std::declval().~U()); ^ prog.cc:26:19: note: in instantiation of template type alias 'has_dtor' requested here

           : type_identity<Op<Args...>>
                            ^

prog.cc:45:1: note: in instantiation of template class 'detail::detector

......

It's werid that once replace type_identity with trival using type = ......, the compiler has no error, demo. For other trival has_member check, type_identity works fine, demo.

So, the only problem here is, for protected dtor, type_identity will force struct detail::detector to check the validity of dtor, while using type = something will not.

I think the solution is simple, just remove type_identity, and use using type = something directly, just like Walter E. Brown's original implementation. But the question is:

why does type_idintity break here, while trival using type = something not?

Chen Li
  • 4,824
  • 3
  • 28
  • 55
  • 2
    This looks like a clang bug to me. [It compiles fine with GCC](https://wandbox.org/permlink/b4szl405SCKudMo8) if you use my `is_destructible` implementation from your previous question. BTW, you should create a [MCVE] to ask a language-lawyer question, there are *too much* irrelevant code here. – llllllllll Nov 25 '18 at 10:02
  • particularly for questions related to type-traits and tamplate-meta-programming, please, ever explicit the exact version of the standard. C++17, in this case, I suppose. – max66 Nov 25 '18 at 10:22
  • @liliscent Sorry, didn't test on gcc and remove unnecessary codes/simplify my codes are my bad. – Chen Li Nov 25 '18 at 10:22
  • @max66 on stackoverfow, I saw someone has said the tag `c++` indicates the latest released version. `type_identity` is available in c++20. I'll tag it later – Chen Li Nov 25 '18 at 10:26
  • I'll report bugs to gcc and clang later – Chen Li Nov 25 '18 at 10:28
  • Not sure that is a correct interpretation of the c++ tag; anyway, I suggest to explicit it ever because, this way, you attract people interested in particular version of the language. And, as explained in c++ tag description, "use a question specific tag for questions related to a specific standard revision" – max66 Nov 25 '18 at 10:32
  • liliscent's codes also compile with icc https://godbolt.org/z/QqjeJh – Chen Li Nov 25 '18 at 11:03
  • @陳力: "*I saw someone has said the tag c++ indicates the latest released version*" Even if that's true, C++20 isn't "the latest released version," since it's not finished. – Nicol Bolas Nov 25 '18 at 20:37

0 Answers0