Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

do decltype needs an expression involving complete type?

Tags:

c++

c++11

Consider the following code, which tries to determine existence of a nested typedef.

  #include<type_traits>
  struct foo;// incomplete type
  template<class T> 
  struct seq
  {
       using value_type = T;
  };
  struct no_type{};
  template<class T>
  struct check_type : std::true_type{};
  template<> 
  struct check_type<no_type> :std::false_type{};
  template<class T> 
  struct has_value_type
  {
    template<class U>
    static auto check(U const&)-> typename U:: value_type;
     static auto check(...)->no_type;  
    static bool const value = check_type<decltype(check(std::declval<T>()))>::value;
    using type = has_value_type;
  };
  int main()
  {
      char c[has_value_type<seq<foo>>::value?1:-1];
      (void)c;
  }

Now invoking has_value_type<seq>::value causes compilation error as invalid use of incomplete type seq<foo>::value_type. does decltype needs a complete type in the expression? If not, how can I remove the error? I am using gcc 4.7 for compilation.

like image 703
abir Avatar asked Apr 20 '26 09:04

abir


2 Answers

Your code is valid C++11, which defines that a toplevel function call that appears as a decltype operand does not introduce a temporary even when the call is a prvalue.

This rule specifically was added to make code as yours valid and to prevent instantiations of the return type (if it is a class template specialization) otherwise needed to determine the access restrictions of a destructor.

like image 187
Johannes Schaub - litb Avatar answered Apr 22 '26 23:04

Johannes Schaub - litb


decltype requires a valid expression, and you certainly can have a valid expression that involves incomplete types. The problem in your case however is

template<class U>
auto check(U const&) -> typename U::value_type;

which has return type foo when U is seq<foo>. You can't return an incomplete type by value, so you end up with an ill-formed expression. You can use a return type of e.g. void_<typename U::value_type> (with template<typename T> struct void_ {};) and your test appears to work.

like image 30
Luc Danton Avatar answered Apr 23 '26 00:04

Luc Danton



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!