Consider the following simple class X
and class template Y<T>
that each define four constexpr
members, three of which have their return types deduced (new C++1y feature), and another subset of three that makes use of another new C++1y feature: the relaxed constexpr
function that now also can have side-effects and a void
return type.
Below a small experiment with the interaction of these features:
#include <type_traits>
#include <utility>
struct X
{
constexpr void fun() {} // OK
constexpr auto gun() {} // OK
auto hun() {} // OK
constexpr auto iun() { return 0; } // OK
};
template<class T>
struct Y
{
constexpr void fun() {} // OK
//constexpr auto gun() {} // ERROR, why?
auto hun() {} // OK
constexpr auto iun() { return 0; } // OK
};
int main()
{
static_assert(std::is_same<void, decltype(std::declval<X>().fun())>::value, "");
static_assert(std::is_same<void, decltype(std::declval<X>().gun())>::value, "");
static_assert(std::is_same<void, decltype(std::declval<X>().hun())>::value, "");
static_assert(std::is_same<int , decltype(std::declval<X>().iun())>::value, "");
static_assert(std::is_same<void, decltype(std::declval<Y<X>>().fun())>::value, "");
//static_assert(std::is_same<void, decltype(std::declval<Y<X>>().gun())>::value, "");
static_assert(std::is_same<void, decltype(std::declval<Y<X>>().hun())>::value, "");
static_assert(std::is_same<int , decltype(std::declval<Y<X>>().iun())>::value, "");
}
Live Example that only compiles on Clang >= 3.4 (because it is the only compiler that supports both the auto return type deduction and the relaxed constexpr
functions)
The gun()
function inside the class template Y<T>
(but not inside the class X
) generates a compiler error:
no return statement in constexpr function
Question : is the combination a constexpr
function with an automatically deduced void
return type inside a class template not possible as per the Standard, or is it a compiler bug in Clang?
As a workaround for a normal template function, you can do:
template<typename T> constexpr auto gun();
template<>
constexpr auto gun<void>() {}
Following the same logic, I think the following should not change your original code too much:
#include <type_traits>
#include <utility>
struct X
{
constexpr auto gun() {}
};
template<class T>
struct Y
{
constexpr auto gun();
};
template<>
constexpr auto Y<X>::gun() { }
int main()
{
static_assert(std::is_same<void, decltype(std::declval<Y<X>>().gun())>::value, "");
}
Also as already stated, an empty return
statement will do the trick.
constexpr auto gun() {return;}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.