Recker
Recker

Reputation: 1975

gcc 6.1 std::result_of compilation error

Consider a small standalone use case wherein I want to determine if a type is a complete or incomplete using

#include <type_traits>
namespace {

struct foo {
    template<class T, std::size_t = sizeof(T)>
    std::false_type  operator()(T&);
    std::true_type operator()(...);
};

struct FooIncomplete;
}


int main() {
    std::result_of<foo(FooIncomplete&)>::type();

    return 0;
}

This compiles fine with gcc 4.9.3 with --std=c++11 flag. However, with gcc 6.1 and --std=c++11 it produces a compilation error as

main.cpp: In function 'int main()':
main.cpp:17:5: error: 'type' is not a member of 'std::result_of<{anonymous}::foo({anonymous}::FooIncomplete&)>'
     std::result_of<foo(FooIncomplete&)>::type();

What am I missing here ? What could be a possible work around ?

Upvotes: 3

Views: 189

Answers (2)

Yakk - Adam Nevraumont
Yakk - Adam Nevraumont

Reputation: 275966

Using something like C++20's is_detected:

namespace details {
  template<template<class...>class Z, class, class...Ts>
struct can_apply:std::false_type{};
  template<class...>struct voider{using type=void;};
  template<class...Ts>using void_t = typename voider<Ts...>::type;

  template<template<class...>class Z, class...Ts>
  struct can_apply<Z, void_t<Z<Ts...>>, Ts...>:std::true_type{};
}
template<template<class...>class Z, class...Ts>
using can_apply=typename details::can_apply<Z,void,Ts...>::type;

template<class T>
using size_of = std::integral_constant<std::size_t, sizeof(T)>;

template<class T>
using is_complete = can_apply< size_of, T >;

we get a trait is_complete that is true iff we can apply sizeof to T.

Be careful with this, because unlike most features the completeness of a type can change between compilation units and even at different spots in the same unit. And C++ doesn't like it when the type some_template<some_args...> changes at different spots in your program.

Live example.

Upvotes: 0

Eloy Martinez
Eloy Martinez

Reputation: 21

Since C++14 result_of::type doesn't exist if T is not callable.

In your case struct FooIncomplete has nothing to call.

Upvotes: 0

Related Questions