Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/templates/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 修改SFINAE习惯用法以使用std::is\u算法检查函数的返回类型_C++_Templates_Template Meta Programming_Sfinae - Fatal编程技术网

C++ 修改SFINAE习惯用法以使用std::is\u算法检查函数的返回类型

C++ 修改SFINAE习惯用法以使用std::is\u算法检查函数的返回类型,c++,templates,template-meta-programming,sfinae,C++,Templates,Template Meta Programming,Sfinae,我正在使用SFINAE习惯用法来检查类型是否具有定义了给定签名的方法(some\u method()): template <typename... Other> struct has_method { static constexpr bool value = has_method<Other...>::value; }; template <typename U, typename... Other> struct has_method<U

我正在使用SFINAE习惯用法来检查类型是否具有定义了给定签名的方法(
some\u method()
):

template <typename... Other>
struct has_method {
    static constexpr bool value = has_method<Other...>::value;
};

template <typename U, typename... Other>
struct has_method<U, Other...> {
    static constexpr bool value =
        has_method<U>::value && has_method<Other...>::value;
};

template <typename U>
struct has_method<U> {
    template <typename T, T>
    struct helper;
    template <typename T>
    static std::uint8_t check(helper<int (*)(size_t), &T::some_method>*);
    template <typename T>
    static std::uint16_t check(...);

    static constexpr bool value = sizeof(check<U>(0)) == sizeof(std::uint8_t);
};
模板
struct有两个方法{
静态constexpr bool value=has_method::value;
};
模板
struct有两个方法{
静态constexpr布尔值=
has_method::value&&has_method::value;
};
模板
struct有两个方法{
模板
结构助手;
模板
静态标准::uint8_t检查(helper*);
模板
静态标准::uint16_t检查(…);
静态constexpr bool value=sizeof(检查(0))==sizeof(标准::uint8\t);
};
我想使用
std::is_算术
对其进行修改,以检查函数的返回类型是否为算术类型。那可能吗?
我尝试使用
static\u assert()
std::is\u算术foo())>::value
修改它,但没有成功

我想这就是你想要的:

struct Unknown {};

template <typename T_>
struct Wrap
{
    typedef T_ type;
};

template <class C_, typename... A_>
struct HasMethodArithmeticReturn
{
    template <class U_>
    static Wrap<decltype(std::declval<U_>().NAME(std::declval<A_>()...))> test(void*);
    template <class U_>
    static Unknown test(...);

    typedef char yes[1];
    typedef char no[2];

    template <typename>
    struct helper
    {
        typedef no type;
    };
    template <typename R_>
    struct helper<Wrap<R_>>
    {
        template <class U_, R_(U_::*)(A_...)>
        struct assist
        {
            typedef yes type;
        };
        template <class U_>
        static typename std::enable_if<std::is_arithmetic<R_>::value, typename assist<U_, &U_::NAME>::type>::type& test(void*);
        template <class U_>
        static no& test(...);
        typedef decltype(test<C_>(0)) type;
    };
    static const bool value = sizeof(yes) == sizeof(typename helper<decltype(test<C_>(0))>::type);
};
struct Unknown{};
模板
结构包裹
{
typedef T_u类型;
};
模板
结构HasMethodArrithmeticReturn
{
模板

static Wrap除了@James Root的答案之外,它允许指定参数,但不允许用户在OP中同时测试多个类,您还可以执行以下操作:

#include <type_traits>

template <typename... Other>
struct has_method {
    static constexpr bool value = has_method<Other...>::value;
};

template <typename U, typename... Other>
struct has_method<U, Other...> {
    static constexpr bool value =
        has_method<U>::value && has_method<Other...>::value;
};

template <typename U>
struct has_method<U> {
    template <typename T>
    static auto typeget(int) -> decltype(T::some_method(size_t{}));
    template <typename T>
    static void typeget(...);


    static constexpr bool value = 
        std::is_arithmetic<decltype(has_method::typeget<U>(0))>::value;
};
#包括
模板
struct有两个方法{
静态constexpr bool value=has_method::value;
};
模板
struct有两个方法{
静态constexpr布尔值=
has_method::value&&has_method::value;
};
模板
struct有两个方法{
模板
静态自动类型获取(int)->decltype(T::some_方法(size_T{}));
模板
静态void typeget(…);
静态constexpr布尔值=
std::is_算术::值;
};
实现语法更简单,但您需要以其他方式支付:您必须为希望提供给函数的每一组参数类型创建一个新模板,这将检测函数是否可以使用参数调用,而不是函数是否具有确切的所需参数


,虽然我已将
size\u t
替换为
uint8\u t
,以演示如果所需类型可以隐式转换为查询类型的成员函数中的参数类型,则表达式的计算结果为true。

编辑:我已更新答案,以允许给定方法采用任意argu不只是有一个
void
签名

我认为这会起作用:

namespace details {
  template<typename...>
  struct voider
  {
      using type=void;
  };

  template<typename T>
  struct GetReturnType;

  // non member function
  template<typename Ret, typename... Args>
  struct GetReturnType<Ret(*)(Args...)>
  {
      using type = Ret;
  };

  // mmeber function
  template<typename Ret, typename C, typename... Args>
  struct GetReturnType<Ret(C::*)(Args...)>
  {
      using type = Ret;
  };
}

template<typename...Ts>
using void_t = typename details::voider<Ts...>::type;

template<typename T, typename=void>
struct has_arithmetic_method : std::false_type{};

template<typename T>
struct has_arithmetic_method<T, void_t<decltype(&T::some_method)>> :  std::is_arithmetic<typename details::GetReturnType<decltype(&T::some_method)>::type>::type{};

实际测试:

int main()
{
    //test the has_arithmetic_method concept
    std::cout << "Struct PassArithmeticMethod: " << std::boolalpha << has_arithmetic_method<PassArithmeticMethod>::value << std::endl;
    std::cout << "Struct PassSomeMethod: " << std::boolalpha << has_arithmetic_method<PassSomeMethod>::value << std::endl;
    std::cout << "Struct FailSomeMethod: " << std::boolalpha << has_arithmetic_method<FailSomeMethod>::value << std::endl;

    std::cout << "Struct PassArithmeticMethod2: " << std::boolalpha << has_arithmetic_method<PassArithmeticMethod2>::value << std::endl;
    std::cout << "Struct PassArithmeticMethod3: " << std::boolalpha << has_arithmetic_method<PassArithmeticMethod3>::value << std::endl;
}
intmain()
{
//测试has\u算术\u方法概念

std::难道我不知道你可以在调用函数时使用
declval
在不知道返回类型的情况下检查一个方法是否存在吗?然后你可以将完整的签名传递给类似上面的东西,但是如果返回类型不是算术的,则将其扩展到sfinae。
int main()
{
    //test the has_arithmetic_method concept
    std::cout << "Struct PassArithmeticMethod: " << std::boolalpha << has_arithmetic_method<PassArithmeticMethod>::value << std::endl;
    std::cout << "Struct PassSomeMethod: " << std::boolalpha << has_arithmetic_method<PassSomeMethod>::value << std::endl;
    std::cout << "Struct FailSomeMethod: " << std::boolalpha << has_arithmetic_method<FailSomeMethod>::value << std::endl;

    std::cout << "Struct PassArithmeticMethod2: " << std::boolalpha << has_arithmetic_method<PassArithmeticMethod2>::value << std::endl;
    std::cout << "Struct PassArithmeticMethod3: " << std::boolalpha << has_arithmetic_method<PassArithmeticMethod3>::value << std::endl;
}