如何编译以下代码?
我意识到编译器对V<double>
不满意,因为它试图为GetterFn
编译我的typedef,但我希望GetterFn
和GetCalc()
可用于类,但忽略原始类型。
我应该如何重新编写这门课程?
#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
}
答案 0 :(得分:3)
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 ]) );
}
然后恰当地重载get_value
:
double get_value(double value) { return value; }
double get_value(Bar value) { return value.getMyFloat(); }
当然,强烈建议使用比get_value
更具描述性的名称。
答案 1 :(得分:1)
double
不能拥有会员功能。因此,使用非会员功能。
答案 2 :(得分:1)
如果不知道你想要为基本类型做什么,建议完整的解决方案有点困难。但是,我建议您使用std::is_fundamental
类型特征。
如果您希望整个成员函数集合只是有条件地存在,那么将它们包装成成员助手类是一个想法:
#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
}
您可能还需要在实际实施中执行一些std::enable_if
。如果您发布更多详细信息,我们可以详细说明。
如果你对更广泛的重新设计持开放态度,Konrad的回答感觉最终结果会更清晰,更简单,但我再次赞成复杂的模板伏都教: - )