2016-12-05 69 views
1

好吧,标题是一个满口,希望足够具体,但我遇到了一个C++问题,我认为这是可能的,我似乎无法找到正确的语法。基于类型名称重载专门的赋值运算符

我有一个简单的基于模板的性能等级:

template <typename T> 
class Property 
{ 
public: 

    Property<T> &operator = (const T &src) 
    { 
    m_data = src; 
    return *this; 
    }; 

    operator const T&() const 
    { 
    return m_data; 
    } 

private: 
    T m_data; 
}; 

我需要从一个QVariant,这也是种类的财产,但没有模板赋值。目前,我分配时明确deferencering值:

Property<QString> p1; 
Property<int> p2; 

p1 = var1.toString(); 
p2 = var2.toInt(); 

这工作,但它是单调乏味的,我敢肯定,编译器能为我做的工作。所以,我试图根据这个属性的typename来实现专门的赋值运算符;换句话说,如果模板专业化是基于一个QString使用一个函数,如果它基于一个int使用另一个函数,等等。

我试过的东西:

Property<QString> &operator = (const QVariant &ref) 
{ 
    m_data = ref.toString(); 
    return *this; 
}; 

或...

template <typename int> &Property<int>::operator = (const QVariant &ref) 
{ 
    m_data = ref.toInt(); 
    return *this; 
}; 

或...

template<> Property<T> &Property<QString>::operator = (const QVariant &ref) 
{ 
    m_data = ref.toString(); 
    return *this; 
} 

..both内和类声明之外,但要徒劳无功。我收到诸如“预期的嵌套名称说明符”,“参数声明中的两个或多个数据类型”等错误。

任何指向正确语法的指针将不胜感激!

PS:第一个声明编译时没有错误,但为<int>添加相同的声明使其不明确,因为只有返回类型不同。

编译器是GCC 4.8.2,启用了--stdc = C++ 11。

+0

尝试'Property&operator =(const T&src)'而不是'Property &operator =(const T&src)'。 –

+1

不是你的主要问题,但建议'operator const T&()const&'(将ref-qualifier加到最后),这样可以减少创建没有警告的悬空引用的风险 –

回答

0

正如Kirill Kobelev在您的问题的评论部分指出的,原始类定义有点不对。现在,我们进行了修复,并添加另一个operator=

template <typename T> 
class Property 
{ 
public: 
    Property & operator=(const T & src) 
    { 
     m_data = src; 
     return *this; 
    } 

    // This one must be specialized 
    Property & operator=(const QVariant & src); 

    const T & operator() const 
    { 
     return m_data; 
    } 

private: 
    T m_data; 
}; 

专业化因此是相当简单的。这里的药粥QStringint

template <> 
Property<QString> & 
Property<QString>::operator=(const QVariant & src) 
{ 
    return operator=(src.toString()); 
} 

template <> 
Property<int> & 
Property<int>::operator=(const QVariant & src) 
{ 
    return operator=(src.toInt()); 
} 

现在你可以自由地直接分配QVariant值,它提供了专业化的任何Property。如果你尝试在没有专门学习的课上做,那么你会得到一个错误。

+0

是的,就是这样。我非常接近“非专业化”赋值运算符,但是却无法做到。 – JvO

2

尽管稻谷的答案看起来是正确的,但对我来说它是一个繁琐的工作,除了QString和int之外,对于所有类型实现一个特殊的赋值运算符。

更简单的解决办法是一次专门赋值运算符的所有,在某种程度上,从内置的转换,该QVariant提供好处:

Property& operator= (const QVariant& src) 
{ 
    assert(src.canConvert<T>()); 
    m_data = src.value<T>(); 
    return *this; 
} 
+1

不幸的是,我无法批准两个答案,但这也相当不错。断言是一个很好的额外! – JvO

+1

这实际上是一个更好的答案。相反,你应该接受。 – paddy

0

我没有信誉评论,也不具备洞察力的专业知识,所以请不要把它当作“答案”。

但是你的问题让我想起了关于Cpp,Overloads和Functions在上的一课。

摘录:

“在上面的例子中,我们使用的函数模板总和两次首次与int类型的参数,而第二个与double类型的参数的编译器已经被实例化,然后调用。每一次函数的适当版本

因此,结果将是与参数a和b以及函数返回的类型相同的变量 在这种特定情况下,泛型类型T被用作求和的参数,编译器甚至能够自动推断出数据类型,而不必在尖括号内明确指定它。“

道歉,如果我错过了这一点,但认为这可能有所帮助。