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.
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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With