如何在没有实例的情况下获取非静态方法的类型?
How to get the type of non-static method without instance?
我正在尝试用 C++ 创建一个模板函数,例如:
template<typename IteratorType>
double evaluate(const IteratorType &rBegin, const IteratorType &rEnd,
double(*function)( const decltype( *IteratorType ) &rObject )) // error, typename not allowed
// I'm unsure if I need to put the reference there, not part of the problem.
{
// ...
}
// not my actual code, just to show an example.
虽然这不起作用,因为我需要一个 class
/struct
的实例来调用非静态方法,
我不能这样做,因为它在一个函数中。
谷歌搜索了一下后,我找到了这个解决方案:
double(*function)( const typename std::iterator_traits<IteratorType>::value_type &rObject )
尽管如您所见,这使用起来很笨拙(而且更改起来很痛苦),尤其是当您尝试创建多个重载时。这似乎也不适用于我的迭代器,所以过了一会儿我意识到:
double(*function)( const typename IteratorType::value_type &rObject)
将是最好的解决方案。
最后我意识到不能保证“IteratorType
”将 value_type
定义为值的类型,指针是一回事。
我有什么方法可以逃脱
double(*function)( const decltype(*IteratorType) &robject)
?
Though as you can see this gets clumsy to use [...]
提供一些模板别名,可以减少笨拙!
template<typename IteratorType>
using ValueType = typename std::iterator_traits<IteratorType>::value_type;
template<typename IteratorType>
using FunctionPtr = double(*)(const ValueType<IteratorType> &);
template<typename IteratorType>
double evaluate(const IteratorType rBegin, const IteratorType rEnd,
FunctionPtr<IteratorType> function) // now you can simply this
{
}
首先你需要一个最简单的例子来说明你的问题。以下是我从您的评论中了解到的内容:
#include <iostream>
#include <vector>
#include <string>
struct MyClass /* final */
{
static double member(std::string const& val) /* noexcept */
{
std::cout << "double MyClass::member(int val): " << val << "\n";
return {}; // return appropriate results
}
};
template<typename IteratorType>
void evaluate(IteratorType rBegin, const IteratorType rEnd,
// WHAT??? other than:
// double(*function)(const typename std::iterator_traits<IteratorType>::value_type &rObject )
{
while (rBegin != rEnd)
{
function(*rBegin);
++rBegin;
}
}
int main()
{
std::vector<std::string> vec{ "1", "2", "3"};
evaluate(vec.cbegin(), vec.cend(), &MyClass::member);
}
Though as you can see this gets clumsy to use [...]
除了 ,如果您的问题是使用std::iterator_traits
,您还有以下两个选择。
选项 - I
喜欢@chtz
在评论中提到,使用
std::declval
获取迭代器的下划线类型如下:
template<typename IteratorType>
void evaluate(IteratorType rBegin, const IteratorType rEnd,
double(*function)(
std::remove_reference_t<decltype(*std::declval<IteratorType>())> const&))
//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--> value_type == std::string
{
// ... code
}
提供一个辅助模板类型别名是个不错的主意:
template<typename IteratorType>
using ValueType = std::remove_reference_t<decltype(*std::declval<IteratorType>())>;
template<typename IteratorType>
void evaluate(IteratorType rBegin, const IteratorType rEnd,
double(*function)(ValueType<IteratorType> const&))
// ^^^^^^^^^^^^^^^^^^^^^^^ value_type == std::string
{
// ... code
}
选项 - II
从 rBegin
,通过将 T&
转换为 T
使用
std::remove_reference_t
.
template<typename IteratorType>
void evaluate(IteratorType rBegin, const IteratorType rEnd,
double(*function)(std::remove_reference_t<decltype(*rBegin)> const&))
// ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---> std::string
{
// ... code
}
我正在尝试用 C++ 创建一个模板函数,例如:
template<typename IteratorType>
double evaluate(const IteratorType &rBegin, const IteratorType &rEnd,
double(*function)( const decltype( *IteratorType ) &rObject )) // error, typename not allowed
// I'm unsure if I need to put the reference there, not part of the problem.
{
// ...
}
// not my actual code, just to show an example.
虽然这不起作用,因为我需要一个 class
/struct
的实例来调用非静态方法,
我不能这样做,因为它在一个函数中。
谷歌搜索了一下后,我找到了这个解决方案:
double(*function)( const typename std::iterator_traits<IteratorType>::value_type &rObject )
尽管如您所见,这使用起来很笨拙(而且更改起来很痛苦),尤其是当您尝试创建多个重载时。这似乎也不适用于我的迭代器,所以过了一会儿我意识到:
double(*function)( const typename IteratorType::value_type &rObject)
将是最好的解决方案。
最后我意识到不能保证“IteratorType
”将 value_type
定义为值的类型,指针是一回事。
我有什么方法可以逃脱
double(*function)( const decltype(*IteratorType) &robject)
?
Though as you can see this gets clumsy to use [...]
提供一些模板别名,可以减少笨拙!
template<typename IteratorType>
using ValueType = typename std::iterator_traits<IteratorType>::value_type;
template<typename IteratorType>
using FunctionPtr = double(*)(const ValueType<IteratorType> &);
template<typename IteratorType>
double evaluate(const IteratorType rBegin, const IteratorType rEnd,
FunctionPtr<IteratorType> function) // now you can simply this
{
}
首先你需要一个最简单的例子来说明你的问题。以下是我从您的评论中了解到的内容:
#include <iostream>
#include <vector>
#include <string>
struct MyClass /* final */
{
static double member(std::string const& val) /* noexcept */
{
std::cout << "double MyClass::member(int val): " << val << "\n";
return {}; // return appropriate results
}
};
template<typename IteratorType>
void evaluate(IteratorType rBegin, const IteratorType rEnd,
// WHAT??? other than:
// double(*function)(const typename std::iterator_traits<IteratorType>::value_type &rObject )
{
while (rBegin != rEnd)
{
function(*rBegin);
++rBegin;
}
}
int main()
{
std::vector<std::string> vec{ "1", "2", "3"};
evaluate(vec.cbegin(), vec.cend(), &MyClass::member);
}
Though as you can see this gets clumsy to use [...]
除了std::iterator_traits
,您还有以下两个选择。
选项 - I
喜欢@chtz 在评论中提到,使用
std::declval
获取迭代器的下划线类型如下:template<typename IteratorType> void evaluate(IteratorType rBegin, const IteratorType rEnd, double(*function)( std::remove_reference_t<decltype(*std::declval<IteratorType>())> const&)) //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^--> value_type == std::string { // ... code }
提供一个辅助模板类型别名是个不错的主意:
template<typename IteratorType> using ValueType = std::remove_reference_t<decltype(*std::declval<IteratorType>())>; template<typename IteratorType> void evaluate(IteratorType rBegin, const IteratorType rEnd, double(*function)(ValueType<IteratorType> const&)) // ^^^^^^^^^^^^^^^^^^^^^^^ value_type == std::string { // ... code }
选项 - II
从
rBegin
,通过将T&
转换为T
使用std::remove_reference_t
.template<typename IteratorType> void evaluate(IteratorType rBegin, const IteratorType rEnd, double(*function)(std::remove_reference_t<decltype(*rBegin)> const&)) // ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ---> std::string { // ... code }