Вопрос

Consider the following code:

#include <iostream>
#include <type_traits>
#include <typeinfo>

struct Base
{
    int f() const;
    double f();
};

struct Derived
: public Base
{
    template <typename T = decltype(std::declval<Derived>().f())> // Modify this
    T g() const;
};

int main()
{
    const Derived x;
    std::cout<<typeid(decltype(x.g())).name()<<std::endl; // Prints "d", not "i"
    return 0;
}

How to modify decltype(std::declval<Derived>().f()) so that it will return int and not double?

I've tried decltype(std::declval<const Derived>().f() but it does not compile.

Это было полезно?

Решение

GCC 4.8.1 likes this:

template <typename T = decltype(std::declval<Base const>().f())> 

You need to tell the compiler that the object through which you make the call is const.

You cannot specify Derived here in this declval because at the point of the call, Derived is an incomplete type. In addition, you don't even need Derived as part of the declval since f() is a member of Base.

Другие советы

You are trying to use Derived in a context where it required to be complete, but it can't be complete yet as it is part of the method's return type which is required to complete the definition. This loop is impossible to solve for the compiler.

You need to use the base class with std::declval<const Base>() and your code will compile.

Throw declval out the window; when your type expression is dependent on function parameters, class members, and/or this it is almost certainly easier and clearer to put it in a trailing return type where you can refer to them by name:

struct Derived
: public Base
{
    Derived() {}
    auto g() const -> decltype(f());
};

I added a user-provided default constructor to Derived so that const Derived x; is well-formed per §8.5/6.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top