The output type constant returned by the function

Is there a way to determine if a function returns a constant or a value that is not a constant? decltype works for links, but it won’t work for types without a link.

 #include <type_traits> template< typename > struct print_type; //undefined int main(){ auto lambda = []()->const int{ return 0; }; print_type< decltype(lambda()) > dt; //print_type< int > print_type< typename std::result_of<decltype(lambda)()>::type > ro; //print_type< int > return 0; } 

I implemented the std::tuple conversion function, which will call a function object for each tuple element and store the result in a new tuple consisting of return types. This does not work for return constant types, which is pretty surprising (but necessary).

+6
source share
3 answers
 #include <iostream> #include <type_traits> #include <utility> template <typename T> struct has_operator { template <typename U> struct SFINAE {}; template <typename U> static std::true_type test(SFINAE<decltype(&U::operator())>*); template <typename U> static std::false_type test(...); static constexpr bool value = std::is_same<decltype(test<T>(nullptr)), std::true_type>::value; }; template <bool value, typename T> struct check_constness; template <typename T> struct check_constness<false, T> { template <typename R, typename... Args> static std::true_type const_or_not(const R(*)(Args...)); static std::false_type const_or_not(...); using type = decltype(const_or_not(std::declval<T*>())); }; template <typename T> struct check_constness<true, T> { template <typename R, typename C, typename... Args> static std::true_type const_or_not(const R(C::*)(Args...)); template <typename R, typename C, typename... Args> static std::true_type const_or_not(const R(C::*)(Args...) const); template <typename R, typename C, typename... Args> static std::true_type const_or_not(const R(C::*)(Args...) const volatile); template <typename R, typename C, typename... Args> static std::true_type const_or_not(const R(C::*)(Args...) volatile); static std::false_type const_or_not(...); using type = decltype(const_or_not(&T::operator())); }; template <typename T> using is_const_ret_type = typename check_constness<has_operator<T>::value, T>::type; int glob() { return 0; } const int cglob() { return 0; } int main() { std::cout << std::boolalpha; int x = 123; auto lambda = []() -> int { return 0; }; auto clambda = []() -> const int { return 0; }; auto closure = [x]() -> int { return x; }; auto cclosure = [x]() -> const int { return x; }; std::cout << is_const_ret_type<decltype(lambda)>::value << std::endl; std::cout << is_const_ret_type<decltype(clambda)>::value << std::endl; std::cout << is_const_ret_type<decltype(glob)>::value << std::endl; std::cout << is_const_ret_type<decltype(cglob)>::value << std::endl; std::cout << is_const_ret_type<decltype(closure)>::value << std::endl; std::cout << is_const_ret_type<decltype(cclosure)>::value << std::endl; } 

Output:

 false true false true false true 

Live demo

+3
source

For non-built-in types, you can use std::is_const and decltype to get what you want.

Example:

 #include <iostream> #include <type_traits> struct A {}; int main() { std::cout << std::boolalpha; { auto lambda = []()->A{ return A(); }; std::cout << std::is_const<decltype(lambda())>::value << std::endl; } { auto lambda = []()->const A{ return A(); }; std::cout << std::is_const<decltype(lambda())>::value << std::endl; } return 0; } 

Output:

  false
 true
+5
source

You can use std :: result_of to get the return type of the called object.

Remember that returning const int is not possible, the compiler will ignore the qualification. GCC warns of this. Something in -Wall -Wextra -pedantic includes this.

0
source

Source: https://habr.com/ru/post/975443/


All Articles