【发布时间】:2016-02-11 08:33:09
【问题描述】:
我想向 C++ 类添加(动态)属性,它可以是多种类型(例如 float、int、bool)。根据其值类型,界面中应显示不同的控件。
为此,我使用 SFINAE 为 type() 函数创建了一个简单的 Property 类:
#include <iostream>
#include <type_traits>
template <class T>
class Property
{
public:
enum Type {
Undefined = -1,
Int,
Float,
Bool,
};
explicit Property(const std::string& name) : name_(name) { }
const std::string& name() const { return name_; }
// specialization for floating point type() getter
template<class U = T,
typename std::enable_if<std::is_floating_point<U>::value>::type* = nullptr>
Type type() const {
return Type::Float;
}
// specialization for integer type() getter
template<class U = T,
typename std::enable_if<std::is_integral<U>::value>::type* = nullptr>
Type type() const {
return Type::Int;
}
// specialization for boolean type() getter
template<class U = T,
typename std::enable_if<std::is_same<U, bool>::value>::type* = nullptr>
Type type() const {
return Type::Bool;
}
private:
std::string name_;
T value_;
};
int main() {
// this works
auto fProp = new Property<float>("float property");
std::cout << fProp->type() << std::endl;
}
到目前为止,这工作得相当好。现在,当我想将其中几个属性存储在一个向量中时,问题就来了。为此,我创建了一个通用接口,并相应地更改了类:
#include <iostream>
#include <type_traits>
#include <vector>
class IProperty
{
// common interface for all typed Property<T>'s
public:
enum Type {
Undefined = -1,
Int,
Float,
Bool,
};
virtual const std::string& name() const = 0;
};
template <class T>
class Property : public IProperty
{
public:
explicit Property(const std::string& name) : name_(name) { }
const std::string& name() const { return name_; }
// specialization for floating point type() getter
template<class U = T,
typename std::enable_if<std::is_floating_point<U>::value>::type* = nullptr>
Type type() const {
return Type::Float;
}
// specialization for integer type() getter
template<class U = T,
typename std::enable_if<std::is_integral<U>::value>::type* = nullptr>
Type type() const {
return Type::Int;
}
// specialization for boolean type() getter
template<class U = T,
typename std::enable_if<std::is_same<U, bool>::value>::type* = nullptr>
Type type() const {
return Type::Bool;
}
private:
std::string name_;
T value_;
};
int main() {
// works
auto fProp = new Property<float>("float property");
std::cout << fProp->type() << std::endl;
std::vector<IProperty*> properties;
properties.push_back(fProp);
// error: 'class IProperty' has no member named 'type'
for (auto iprop : properties) {
std::cout << iprop->type() << std::endl;
}
}
如您所见,我无法调用type() 方法,因为它没有为IProperty 类定义。我尝试定义一个纯虚拟IProperty::type(),但这当然不适用于模板派生类。
我有什么选择?
【问题讨论】:
-
这不是 std::is_integral 和 std::is_same 雄心勃勃吗?