[英]How do I get this template class to compile for Classes and primitive types?
How do I get the following code to compile? 如何编译以下代码?
I realize that the compiler is not happy with V<double>
because it tries to compile my typedef for GetterFn
, but I would like GetterFn
and GetCalc()
to be available for classes, but ignored for primitive types. 我意识到编译器对
V<double>
不满意,因为它试图为GetterFn
编译我的typedef,但我希望GetterFn
和GetCalc()
可用于类,但忽略了原始类型。
How should I recode this class? 我该如何重新编写这门课程?
#include <vector>
using namespace std;
class Bar
{
public:
float getMyFloat() const { return 42.5; }
};
template< typename T >
class V
{
public:
typedef float (T::*GetterFn)() const;
void getCalc( std::vector<double>& vec, GetterFn fn ) const
{
vec.clear();
for ( size_t i=0; i<m_v.size(); ++i )
vec.push_back( m_v[ i ].*(fn)() );
}
private:
vector<T> m_v;
};
int main(int argc, char** argv)
{
V<Bar> vb; // ok
V<double> vd; // compiler not happy
}
Alf's slightly snarky answer is indeed the easiest way. 阿尔夫略带讽刺的回答确实是最简单的方法。 Instead of having the
GetterFn
be a member function pointer, just use an overloaded free function to get the value: 不要让
GetterFn
成为成员函数指针,只需使用重载的自由函数来获取值:
void getCalc( std::vector<double>& vec) const
{
vec.clear();
for ( size_t i=0; i<m_v.size(); ++i )
vec.push_back( get_value(m_v[ i ]) );
}
and then just overload get_value
appropriately: 然后恰当地重载
get_value
:
double get_value(double value) { return value; }
double get_value(Bar value) { return value.getMyFloat(); }
Of course, a more descriptive name than get_value
is highly recommended. 当然,强烈建议使用比
get_value
更具描述性的名称。
A double
cannot have a member function. double
精灵不能有会员功能。 Ergo, use a non-member function. 因此,使用非成员函数。
It's a bit hard to suggest the complete solution without knowing what you want to do for fundamental types. 如果不知道你想要为基本类型做什么,建议完整的解决方案有点困难。 However, at the heart I suggest you employ the
std::is_fundamental
type trait. 但是,我建议您使用
std::is_fundamental
类型特征。
If you want entire collections of member functions to exist only conditionally, then perhaps wrapping them into a member helper class is one idea: 如果您希望整个成员函数集合仅有条件地存在,那么将它们包装到成员助手类中是一个想法:
#include <vector>
#include <type_traits>
#include <cstddef>
class Bar
{
public:
float getMyFloat() const { return 42.5; }
};
template< typename T >
class V
{
private:
static const bool m_primitive = std::is_fundamental<T>::value; // convenience
template <bool B, typename U> struct Helper;
template <typename U> struct Helper<false, U>
{
typedef float (T::*GetterFnType)() const;
void getCalc(std::vector<double> & v1, std::vector<U> const & v2, GetterFnType f)
{
v1.clear();
for (std::size_t i = 0; i < v2.size(); ++i)
v1.push_back((v2[i].*f)());
}
};
public:
// use Helper<m_primitive, T>::GetterFn and Helper<m_primitive, T>::getCalc() here
private:
std::vector<T> m_v;
};
int main(int argc, char** argv)
{
V<Bar> vb; // ok
V<double> vd; // compiler also happy
}
You'll probably also have to do some std::enable_if
in the actual implementation. 您可能还需要在实际实现中执行一些
std::enable_if
。 If you post more details, we can elaborate. 如果您发布更多详细信息,我们可以详细说明。
If you're open to a broader redesign, Konrad's answer feels like the final result would be somewhat cleaner and simpler, but then again I'm all in favour of convoluted template voodoo :-) 如果你对更广泛的重新设计持开放态度,康拉德的回答感觉最终结果会更清晰,更简单,但我再次赞成复杂的模板伏都教:-)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.