成员函数参数的类型
Type of member functions arguments
我正在使用 C++11 尝试从函数名称中获取函数参数的类型,前提是函数签名是明确的。最终,我试图检查参数是否正是我想要的类型 before 我调用一个函数。
到目前为止,由于这个解决方案,我可以使用非成员函数来完成它:
Unpacking arguments of a functional parameter to a C++ template class
我稍微编辑了一下得到以下内容 class:
template<typename T>
struct FunctionSignatureParser; // unimplemented primary template
template<typename Result, typename...Args>
struct FunctionSignatureParser<Result(Args...)>
{
using return_type = Result;
using args_tuple = std::tuple<Args...>;
template <size_t i> struct arg
{
typedef typename std::tuple_element<i, args_tuple>::type type;
};
};
例如我可以在编译时检查一个函数的类型:
short square(char x) { // 8-bit integer as input, 16-bit integer as output
return short(x)*short(x);
}
int main() {
char answer = 42;
static_assert(std::is_same<char, FunctionSignatureParser<decltype(square)>::arg<0>::type>::value, "Function 'square' does not use an argument of type 'char'");
static_assert(std::is_same<short, FunctionSignatureParser<decltype(square)>::return_type>::value, "Function 'square' does not return a value of type 'short'");
short sqrAnswer = square(answer);
std::cout << "The square of " << +answer << " is " << +sqrAnswer << std::endl;
return 0;
}
但是当我想检查成员函数的类型时,有些编译器不乐意:
struct Temperature
{
double degrees;
Temperature add(double value);
};
int main() {
Temperature t{16};
double increment{8};
static_assert(std::is_same<double, FunctionSignatureParser<decltype(t.add)>::arg<0>::type>::value, "Method 'Temperature::add' does not use an argument of type 'double'");
std::cout << t.degrees << u8" \u00b0C + " << increment << " == " << t.add(increment).degrees << u8" \u00b0C" << std::endl;
return 0;
}
这是 gcc 6.3 必须说的:
error: invalid use of non-static member function ‘Temperature Temperature::add(double)’
这是 clang 4.0 必须说的:
error: reference to non-static member function must be called
我已经尝试了这些选项,但无济于事:
decltype(Temperature::add)
decltype(std::declval<Temperature>().add)
decltype
中的非静态成员函数有什么问题?由于不计算 decltype
中的表达式,因此 static
限定符应该无关紧要,对吧?
郑重声明,MSVC12 在这种情况下成功了。不过,我无法判断 Microsoft 编译器是对还是错。 (请不要让这个线程成为编译器war)
此外,如果您有不涉及初始方法的参数检查解决方案,我也愿意接受。
您需要对成员函数进行另一个模板特化,如下所示:
template<typename ClassType, typename Result, typename...Args>
struct FunctionSignatureParser<Result(ClassType::*)(Args...)>
{
using return_type = Result;
using args_tuple = std::tuple<Args...>;
template <size_t i> struct arg
{
typedef typename std::tuple_element<i, args_tuple>::type type;
};
};
并且可以这样使用:
static_assert(std::is_same<double, FunctionSignatureParser<decltype(&Temperature::add)>::arg<0>::type>::value, "Method 'Temperature::add' does not use an argument of type 'double'");
这适用于 gcc 7.2,尚未测试其他编译器
我正在使用 C++11 尝试从函数名称中获取函数参数的类型,前提是函数签名是明确的。最终,我试图检查参数是否正是我想要的类型 before 我调用一个函数。
到目前为止,由于这个解决方案,我可以使用非成员函数来完成它: Unpacking arguments of a functional parameter to a C++ template class
我稍微编辑了一下得到以下内容 class:
template<typename T>
struct FunctionSignatureParser; // unimplemented primary template
template<typename Result, typename...Args>
struct FunctionSignatureParser<Result(Args...)>
{
using return_type = Result;
using args_tuple = std::tuple<Args...>;
template <size_t i> struct arg
{
typedef typename std::tuple_element<i, args_tuple>::type type;
};
};
例如我可以在编译时检查一个函数的类型:
short square(char x) { // 8-bit integer as input, 16-bit integer as output
return short(x)*short(x);
}
int main() {
char answer = 42;
static_assert(std::is_same<char, FunctionSignatureParser<decltype(square)>::arg<0>::type>::value, "Function 'square' does not use an argument of type 'char'");
static_assert(std::is_same<short, FunctionSignatureParser<decltype(square)>::return_type>::value, "Function 'square' does not return a value of type 'short'");
short sqrAnswer = square(answer);
std::cout << "The square of " << +answer << " is " << +sqrAnswer << std::endl;
return 0;
}
但是当我想检查成员函数的类型时,有些编译器不乐意:
struct Temperature
{
double degrees;
Temperature add(double value);
};
int main() {
Temperature t{16};
double increment{8};
static_assert(std::is_same<double, FunctionSignatureParser<decltype(t.add)>::arg<0>::type>::value, "Method 'Temperature::add' does not use an argument of type 'double'");
std::cout << t.degrees << u8" \u00b0C + " << increment << " == " << t.add(increment).degrees << u8" \u00b0C" << std::endl;
return 0;
}
这是 gcc 6.3 必须说的:
error: invalid use of non-static member function ‘Temperature Temperature::add(double)’
这是 clang 4.0 必须说的:
error: reference to non-static member function must be called
我已经尝试了这些选项,但无济于事:
decltype(Temperature::add)
decltype(std::declval<Temperature>().add)
decltype
中的非静态成员函数有什么问题?由于不计算 decltype
中的表达式,因此 static
限定符应该无关紧要,对吧?
郑重声明,MSVC12 在这种情况下成功了。不过,我无法判断 Microsoft 编译器是对还是错。 (请不要让这个线程成为编译器war)
此外,如果您有不涉及初始方法的参数检查解决方案,我也愿意接受。
您需要对成员函数进行另一个模板特化,如下所示:
template<typename ClassType, typename Result, typename...Args>
struct FunctionSignatureParser<Result(ClassType::*)(Args...)>
{
using return_type = Result;
using args_tuple = std::tuple<Args...>;
template <size_t i> struct arg
{
typedef typename std::tuple_element<i, args_tuple>::type type;
};
};
并且可以这样使用:
static_assert(std::is_same<double, FunctionSignatureParser<decltype(&Temperature::add)>::arg<0>::type>::value, "Method 'Temperature::add' does not use an argument of type 'double'");
这适用于 gcc 7.2,尚未测试其他编译器