10

我在找什么:我有一个模板类,如果该类有想要的函数,我想调用一个函数,比如:

template<class T> do_something() {
    if constexpr (std::is_member_function_pointer<decltype(&T::x)>::value) {
        this->_t->x(); // _t is type of T*
    }
}

会发生什么:T如果不带函数,编译器不会编译。小例子:

#include <type_traits>
#include <iostream>

class Foo {
public:
    void x() { }
};

class Bar { };

int main() {
    std::cout << "Foo = " << std::is_member_function_pointer<decltype(&Foo::x)>::value << std::endl;
    std::cout << "Bar = " << std::is_member_function_pointer<decltype(&Bar::x)>::value << std::endl;
    return 0;
}

编译器说:

is_member_function_pointer.cpp:17:69: error: no member named 'x' in 'Bar'; did you mean 'Foo::x'?
    std::cout << "Bar = " << std::is_member_function_pointer<decltype(&Bar::x)>::value << std::endl;

那么,std::is_member_function_pointer当我不能在其中使用它时,它是if constexpr什么?如果我只使用this->_t->x()编译器,肯定也会失败。

4

1 回答 1

17

is_member_function_pointer不检测实体的存在T::x,它假定它存在并返回它是否是成员函数指针。

如果要检测它是否存在,可以使用检测成语。例子:

#include <experimental/type_traits>

template<class T>
using has_x = decltype(&T::x);

template<class T> void do_something(T t) {
    if constexpr (std::experimental::is_detected<has_x, T>::value) {
        t.x(); 
    }
}

struct Foo {
    void x() { }
};

struct Bar { };

int main() {
    do_something(Foo{});
    do_something(Bar{});
}

godbolt.org 上的实时示例


我写了一篇关于检查不同 C++ 标准版本中表达式有效性的一般问题的文章:

“使用 C++17 就地检查表达式有效性”

于 2019-03-14T11:56:33.423 回答