检测是否定义了具有特定签名的 function/operator/method
Detect if a function/operator/method having certain signature is defined
来自 问题,我们如何检测(在编译时)是否定义了具有特定签名的 function/operator/method?
从链接的问题和查看关于 std::void_t 的 cppreference 我们可以写(提前 C++17)
#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;
}
打印
X has someFunc()
Y has NOT someFunc()
但是如果我们想测试一个类型 someFunc
不仅要定义而且还要有特定的签名怎么办?
虽然我使用的是 C++17,但也欢迎使用任何其他标准版本的答案。
如果你打算检查一个类型是否有一个方法 someFunc()
compatible (in-vocable with) a given signature) and return a给定类型,你可以修改你的代码如下
#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{});
}
缺点:您也从第三次调用中获得 "has someFunc()",因为最后一个参数 (a int
) 与最后一个预期参数 (a long
) 兼容。
来自
从链接的问题和查看关于 std::void_t 的 cppreference 我们可以写(提前 C++17)
#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;
}
打印
X has someFunc()
Y has NOT someFunc()
但是如果我们想测试一个类型 someFunc
不仅要定义而且还要有特定的签名怎么办?
虽然我使用的是 C++17,但也欢迎使用任何其他标准版本的答案。
如果你打算检查一个类型是否有一个方法 someFunc()
compatible (in-vocable with) a given signature) and return a给定类型,你可以修改你的代码如下
#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{});
}
缺点:您也从第三次调用中获得 "has someFunc()",因为最后一个参数 (a int
) 与最后一个预期参数 (a long
) 兼容。