Yahoo Answers is shutting down on May 4th, 2021 (Eastern Time) and beginning April 20th, 2021 (Eastern Time) the Yahoo Answers website will be in read-only mode. There will be no changes to other Yahoo properties or services, or your Yahoo account. You can find more information about the Yahoo Answers shutdown and how to download your data on this help page.

C++: Why am I getting the error "expected type-specifier" when using declval as a template argument?

Here is the function I'm dealing with:

    template <typename T, typename C = std::declval<T>> T & f(C c = C()) {

        return c;

    }

It's supposed to run std::declval[1] through the function f. I've pinpointed the problem down to the the default template argument. It seems the compiler is not interpreting std::declval as a type. Why? I'm getting the following errors:

    prog.cpp:17:36: error: expected type-specifier

    prog.cpp:17:36: error: expected '>'

    prog.cpp: In function 'int main()':

    prog.cpp:23:10: error: no matching function for call to 'f()'

    prog.cpp:23:19: error: no matching function for call to 'f()'

So I tried using decltype on it:

    template <typename T, typename C = decltype( std::declval<T> )> T & f(C c = C()) {

        return c;

    }

The errors go away until I have to call f:

    f<A>();

(Where A is an arbitrary class; remember that I'm trying to run std::declval through the function; so try and think of the function f as std::declval<A>).

But I get a large amount of template errors, most of them saying that C is A && when I call f with f<A>(). I never wanted C to be an rvalue reference, so then I try to take out the reference using std::remove_reference[2]:

    template <typename T, typename C = std::remove_reference<decltype( std::declval<T> )>::type> T & f(C c = C()) {

        return c;

    }

But then I get the exact same errors. What could I be doing wrong? Why isn't std::declval<T> deduced as a type? If you guys need context, here's what I have:

    #include <utility>

    #include <type_traits>

    struct B;

    struct A {

        void operator *(const B &) {}

    };

    struct B {

        void operator *(int x) const {}

    };

    inline void operator *(int a, const B & b) {

        return b * a;

    }

    template <typename T, typename C = std::remove_reference<decltype( std::declval<T> )>::type> T & f(C c = C()) {

        return c;

    }

    int main() {

        f<A>() * f<B>();

    }

The above code surrounding the function does nothing special. What you should be focusing on is why std::declval<T> is not a type and how I can fix this. Here is a demo:

    http://ideone.com/Zluu3d#view_edit_box

All answers and suggestions are appreciated.

    [1]: Found in header <utility>. Converts any type T into a reference type, thus allowing the ability to use member functions without specifying constructors

    [2]: Found in header <type_traits>. Removes a given reference

Update:

@Cubbi I'm just trying to run std::declval through the function f in the template arguments. Take this example where it uses std::less in the roughly same way:

    template <typename A, typename B, typename U = std::less<int>>

    bool f(A a, B b, U u = U())

    {

        return u(a, b);

    }

I'm trying to use std::declval in the same way. But the argument isn't deduced as a type. I'm just trying to find out why and how to fix this.

2 Answers

Relevance
  • ?
    Lv 7
    9 years ago
    Favorite Answer

    std::declval<T> is most definitely not a type, it's a function, and there is no way to "fix" this.

    What exactly are you trying to achieve?

    EDIT:

    std::less<int> is a type (specifically, a class type with an overloaded operator()).

    std::declval<T> is a function, it is not a type. It cannot be used the same way.

    (additionally, declval<T> is a very special function in that it cannot be called: it can only be used inside a decltype expression)

  • 4 years ago

    Expected Type-specifier

Still have questions? Get your answers by asking now.