简体   繁体   中英

Deducing constness of type returned by function

Is there a way to tell whether a function returns a const or a non-const value? decltype works for references, but it won't work for non-reference types.

#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 a std::tuple transform function, that will call a function object on each tuple element and store the result in a new tuple composed of return types. This doesn't work for const return types, which is pretty surprising (but needed).

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
#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

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

Remember that returning a const int is impossible, the compiler will ignore the qualification. GCC has a warning for this. Something in -Wall -Wextra -pedantic turns that on.

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM