Reputation: 9906
#include <string>
#include <type_traits>
class C
{
static auto func() { return std::string("hello"); }
static_assert(std::is_same<decltype(func()), std::string>::value, "");
};
Neither GCC nor Clang accept this, saying that func
is used before it is defined. Why?
Changing the deduced auto
return type to std::string
makes it work.
Upvotes: 3
Views: 571
Reputation: 69884
In addition to other answers, a possible workaround is to defer the check to a static function and rely on the optimiser to remove all redundant code.
In a release build, this should be zero cost:
#include <string>
#include <type_traits>
#include <iostream>
struct C
{
static auto func() {
check_same();
return std::string("hello");
}
private:
static void check_same()
{
static_assert(std::is_same<decltype(func()), std::string>::value, "");
}
};
int main()
{
std::cout << C::func() << '\n';
}
Upvotes: 1
Reputation: 477020
The decltype
construction produces the declared type of an identifier or expression. When func
is declared with a return type, then the type of the call expression func()
is known and everything works as expected.
However, when func
is declared with the return type placeholder auto
, then the declaration of func
depends on its definition, so the type of func
, and hence of the expression func()
, is not known until the function has been defined.
When you define a class member function inline in the class definition, this is as if the definition were to appear right after the end of the class definition (that is, the function bodies may make reference to names that are lexically declared later in the class definition). The consequence of this and the semantics of auto
is that your function auto func
is not actually fully declared until the end of the class definition, and thus the type of func()
cannot be known until then.
Upvotes: 4