我正在尝试在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)
? 最佳答案
首先,您需要一个最小的例子来解决您的问题。这是我从您的评论中了解的内容:
#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);
}
除了@Const's answer之外,如果您的问题是使用
std::iterator_traits
,那么您还有以下两个选择。像@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
}
(See live demo)在
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
}
(See live demo)