C++ 检测是否定义了具有特定签名的函数/运算符/方法
从这个问题出发,我们如何在编译时检测是否定义了具有特定签名的函数/运算符/方法 通过链接的问题和参考资料,我们可以提前编写C++17C++ 检测是否定义了具有特定签名的函数/运算符/方法,c++,sfinae,C++,Sfinae,从这个问题出发,我们如何在编译时检测是否定义了具有特定签名的函数/运算符/方法 通过链接的问题和参考资料,我们可以提前编写C++17 #include<iostream> #include<type_traits> #include<utility> class X { public: int someFunc() const{ return 9; } }; class Y{}; template<typename, typename = std::
#include<iostream>
#include<type_traits>
#include<utility>
class X { public: int someFunc() const{ return 9; } };
class Y{};
template<typename, typename = std::void_t<>> struct Has_someFunc
: std::false_type{};
template<typename T> struct Has_someFunc<T, std::void_t<decltype(std::declval<T>().someFunc())>>
: std::true_type{};
template<typename T>
void f(const T& v){
if constexpr(Has_someFunc<T>::value)
std::cout << "has someFunc()\n";
else
std::cout << "has NOT someFunc()\n";
}
int main()
{
std::cout << "X "; f(X{});
std::cout << "Y "; f(Y{});
return 0;
}
但是,如果我们想测试一个类型,使其不仅要定义someFunc,而且还要具有特定的签名,该怎么办
尽管我使用的是C++17,但也欢迎在标准的任何其他版本中使用答案。如果您想检查某个类型是否有一个方法someFunc,该方法在vocable中与给定签名兼容并返回给定类型,您可以按如下方式修改代码
#include<iostream>
#include<type_traits>
#include<utility>
class X
{ public: int someFunc (int, long) const { return 9; } };
class Y
{ };
template <typename, typename = void>
struct Has_someFunc : public std::false_type
{ };
template <typename T, typename RType, typename ... Args>
struct Has_someFunc<std::tuple<T, RType, Args...>, std::enable_if_t<
std::is_same_v<RType,
decltype(std::declval<T>().someFunc(std::declval<Args>()...))>>>
: public std::true_type
{ };
template <typename RType, typename ... Args, typename T>
void f (T const & v)
{
if constexpr (Has_someFunc<std::tuple<T, RType, Args...>>::value)
std::cout << "has someFunc()\n";
else
std::cout << "has NOT someFunc()\n";
}
int main()
{
std::cout << "X "; f<int>(X{});
std::cout << "X "; f<int, int, long>(X{});
std::cout << "X "; f<int, int, int>(X{});
std::cout << "Y "; f<int>(Y{});
}
缺点:由于最后一个参数a int与最后一个预期参数a long兼容,因此第三次调用时也会得到someFunc。您想知道someFunc是否可以使用给定的签名进行调用这很简单,从代码开始,还是存在一个完全具有给定签名的someFunc?在第二种情况下:如果有一个与给定签名兼容的模板someFunc呢?对于我当前的需要,你的第一句话就足够了,也就是说,如果我可以使用可转换为现有参数的参数调用该方法,然后返回一个可转换为所需类型的结果。但我也想知道如何对类型更严格。为第一种情况添加了一个答案:对代码进行简单修改。如果你想更严格地检查一个准确的签名。。。也许你应该解释清楚你到底想要什么。
#include<iostream>
#include<type_traits>
#include<utility>
class X
{ public: int someFunc (int, long) const { return 9; } };
class Y
{ };
template <typename, typename = void>
struct Has_someFunc : public std::false_type
{ };
template <typename T, typename RType, typename ... Args>
struct Has_someFunc<std::tuple<T, RType, Args...>, std::enable_if_t<
std::is_same_v<RType,
decltype(std::declval<T>().someFunc(std::declval<Args>()...))>>>
: public std::true_type
{ };
template <typename RType, typename ... Args, typename T>
void f (T const & v)
{
if constexpr (Has_someFunc<std::tuple<T, RType, Args...>>::value)
std::cout << "has someFunc()\n";
else
std::cout << "has NOT someFunc()\n";
}
int main()
{
std::cout << "X "; f<int>(X{});
std::cout << "X "; f<int, int, long>(X{});
std::cout << "X "; f<int, int, int>(X{});
std::cout << "Y "; f<int>(Y{});
}