Detecting void method in c++ template metaprogramming

二次信任 提交于 2019-12-11 04:49:24

问题


I am trying to write a template metafunction to detect if a type has a member function with void type.

Currently I am able to use SFINAE to detect if a member function has a definite type such as double, int, etc. using something like

 template<typename C> static auto Test(void*) -> decltype(int{std::declval<C>().foo()}, Yes{});

And of course I can invert that (as shown in the attached code snippet) to test that it is not int, but I am unable to figure out how to test that it is void.

The code snippet below currently outputs

A  does not have void foo
B  has void foo
C  has void foo

However, C's foo() method has type double, and thus this is the incorrect output. How can I adjust it to correctly check for a void foo()?

#include <iostream>
#include <memory>

class A {
public:
    int foo() {
        return 0;
    }
};

class B {
public:
    void foo() {
    }
};

class C {
public:
    double foo() {
        return 0;
    }
};

template <typename T>
class has_void_foo {
private:
  typedef char Yes;
  typedef Yes No[2];

  template<typename C> static auto Test(void*) -> decltype(int{std::declval<C>().foo()}, Yes{});
  template<typename> static No& Test(...);

public:
    static bool const value = sizeof(Test<T>(0)) != sizeof(Yes);
};

int main(void) {
    std::cout << "A ";
    if (has_void_foo<A>::value) {
        std::cout << " has void foo";
    } else {
        std::cout << " does not have void foo";
    }
    std::cout << std::endl << "B ";
    if (has_void_foo<B>::value) {
        std::cout << " has void foo";
    } else {
        std::cout << " does not have void foo";
    }
    std::cout << std::endl << "C ";
    if (has_void_foo<C>::value) {
        std::cout << " has void foo";
    } else {
        std::cout << " does not have void foo";
    }
    std::cout << std::endl;

    return 0;
}

回答1:


It follows a possible solution based on a constexpr function:

#include <type_traits>

struct A {
    int foo() {
        return 0;
    }
};

struct B {
    void foo() {
    }
};

struct C {
    double foo() {
        return 0;
    }
};

template<typename T, typename R, typename... Args>
constexpr bool has_void_foo(R(T::*)(Args...)) { return std::is_void<R>::value; }

int main() {
    static_assert(not has_void_foo(&A::foo), "!");
    static_assert(has_void_foo(&B::foo), "!");
    static_assert(not has_void_foo(&C::foo), "!");
}


来源:https://stackoverflow.com/questions/42809992/detecting-void-method-in-c-template-metaprogramming

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!