模板元编程以精确匹配函数签名
Template metaprogramming to match function signature exactly
使用模板元编程可以查询类型的属性。例如,在下面的例子中,我正在检查某个类型是否有一个成员函数 "foo",它接受另一个类型作为参数。
有没有办法检查参数类型是否完全匹配模板与转换为模板的参数类型,例如double 或 char 可以转换为 float(导致 main 打印 true 两次)但我想看看是否有一种方法来构造 my_test_t
以便它完美匹配,即 main()
打印 false 除非T2 = float
.
struct S2
{
int foo(float x)
{
return 0;
}
};
template <typename T1, typename T2>
using my_test_t = decltype(declval<T1>().foo(declval<T2>()));
template <typename T1, typename T2, typename = void>
struct is_formed : std::false_type
{
};
template <typename T1, typename T2>
struct is_formed<T1, T2, void_t<my_test_t<T1, T2>>> : std::true_type
{
};
int main()
{
cout << boolalpha << is_formed<S2, double>::value << endl;
cout << boolalpha << is_formed<S2, char>::value << endl;
}
您可以尝试使用 std::is_same 来匹配 foos 参数的确切类型,首先您必须在结构中定义一个类型来进行比较。
可能有更好的方法,我不知道。
#include <type_traits>
#include <utility>
template <typename C, typename P>
auto test(short) -> std::false_type;
template <typename C, typename P>
auto test(int)
-> decltype(static_cast<decltype(std::declval<C&>().foo(std::declval<P>())) (C::*)(P)>(&C::foo)
, std::true_type{});
template <typename C, typename P>
using my_test_t = decltype(test<C, P>(0));
你快到了。我更改了测试,以便我获取 foo
的地址并通过 static_cast
将其指向自身来测试结果成员指针的类型。
#include <type_traits>
#include <iostream>
using namespace std;
struct S2
{
int foo(float x)
{
return 0;
}
};
template <typename T1, typename T2>
using my_test_t = decltype( static_cast<int(T1::*)(T2)>(&T1::foo) );
template <typename T1, typename T2, typename = void>
struct is_formed : std::false_type
{ };
template <typename T1, typename T2>
struct is_formed<T1, T2, void_t< my_test_t<T1,T2> >> : std::true_type
{ };
int main()
{
cout << boolalpha << is_formed<S2, float>::value << endl; // true
cout << boolalpha << is_formed<S2, double>::value << endl; // false
cout << boolalpha << is_formed<S2, char>::value << endl; // false
}
(上面的代码用 C++17 编译,因为 C++14 中没有 std::void_t - 你需要自己写。)
使用模板元编程可以查询类型的属性。例如,在下面的例子中,我正在检查某个类型是否有一个成员函数 "foo",它接受另一个类型作为参数。
有没有办法检查参数类型是否完全匹配模板与转换为模板的参数类型,例如double 或 char 可以转换为 float(导致 main 打印 true 两次)但我想看看是否有一种方法来构造 my_test_t
以便它完美匹配,即 main()
打印 false 除非T2 = float
.
struct S2
{
int foo(float x)
{
return 0;
}
};
template <typename T1, typename T2>
using my_test_t = decltype(declval<T1>().foo(declval<T2>()));
template <typename T1, typename T2, typename = void>
struct is_formed : std::false_type
{
};
template <typename T1, typename T2>
struct is_formed<T1, T2, void_t<my_test_t<T1, T2>>> : std::true_type
{
};
int main()
{
cout << boolalpha << is_formed<S2, double>::value << endl;
cout << boolalpha << is_formed<S2, char>::value << endl;
}
您可以尝试使用 std::is_same 来匹配 foos 参数的确切类型,首先您必须在结构中定义一个类型来进行比较。
可能有更好的方法,我不知道。
#include <type_traits>
#include <utility>
template <typename C, typename P>
auto test(short) -> std::false_type;
template <typename C, typename P>
auto test(int)
-> decltype(static_cast<decltype(std::declval<C&>().foo(std::declval<P>())) (C::*)(P)>(&C::foo)
, std::true_type{});
template <typename C, typename P>
using my_test_t = decltype(test<C, P>(0));
你快到了。我更改了测试,以便我获取 foo
的地址并通过 static_cast
将其指向自身来测试结果成员指针的类型。
#include <type_traits>
#include <iostream>
using namespace std;
struct S2
{
int foo(float x)
{
return 0;
}
};
template <typename T1, typename T2>
using my_test_t = decltype( static_cast<int(T1::*)(T2)>(&T1::foo) );
template <typename T1, typename T2, typename = void>
struct is_formed : std::false_type
{ };
template <typename T1, typename T2>
struct is_formed<T1, T2, void_t< my_test_t<T1,T2> >> : std::true_type
{ };
int main()
{
cout << boolalpha << is_formed<S2, float>::value << endl; // true
cout << boolalpha << is_formed<S2, double>::value << endl; // false
cout << boolalpha << is_formed<S2, char>::value << endl; // false
}
(上面的代码用 C++17 编译,因为 C++14 中没有 std::void_t - 你需要自己写。)