C++模板专用化 - 无法匹配函数定义

  • 本文关键字:函数 定义 专用 C++ c++ c++14
  • 更新时间 :
  • 英文 :


我已经用头撞墙一天半了,试图学习模板专业化和std::enable_if((。 我没有得到什么。 我正在尝试允许从类方法中指定返回类型,基于编译时的类类型和用户规范。 例如,如果类类型是整数,我可能需要该方法的浮点返回类型(或 int(。

我的实际用例是一个数组,我正在平均其中的所有值。 我什至可能想要一个布尔返回值来反映二进制"投票"的结果。 有很多组合。必须有一种方法可以做到这一点,而无需单独创建所有重载。 我的示例代码是我能做的最简单的代码。

我将不胜感激任何指示。 如果确实是这样称呼的,我该如何进行这种部分专业化?

#include <string>
template <class T>
class Test {
public:
Test(T val) { val_ = val; }
template <typename U> U halve ();
private:
T val_;
};

template<class T> template<typename U>
U Test<T>::halve() {
throw std::invalid_argument("Cannot halve non-numeric objects");
}
template<class T> template<typename U>  //example: T=int, U=float
typename std::enable_if_t<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value, U>
Test<T>::halve() {  //error C2244 - unable to match function definition to an existing declaration
return ((U)val_ / (U)2);
}

int main() {
Test<int> t1(5);
float f = t1.halve<float>();    //expect 2.5
int i = t1.halve<int>();        //expect 2
Test<std::string> t2((std::string)"blah");
int t2h = t2.halve<int>();  //this will throw (by design)
return 0;
}

Sam 的评论是正确的 - 你不能部分专用成员函数。解决方法是在类主体中使用enable_if_t。这样的事情应该有效:

template <class T> class Test {
public:
Test(T val) { val_ = val; }
template <typename U>
std::enable_if_t<std::is_arithmetic<T>::value && std::is_arithmetic<U>::value, U>
halve () {  
return ((U)val_ / (U)2);
}
template <typename U>
std::enable_if_t<!(std::is_arithmetic<T>::value && std::is_arithmetic<U>::value), U>
halve () {  
throw std::invalid_argument("Cannot halve non-numeric objects");
}
private:
T val_;
};

有一种更简单的方法可以做到这一点,只需使用模板声明一个 main 函数,然后将其专门用于您需要的任何类型。我添加了 int 和 float,它返回正确的值。

传入任何其他内容并抛出,因为将调用第一个halve函数。

template <class T>
class Test
{
public:
Test(T val)
{
val_ = val;
}
// Default function
template<class MainType>
MainType halve()
{
throw std::invalid_argument("Cannot halve non-numeric objects");
}
// Int specialization
template<>
int halve<int>()
{
return (static_cast<int>(this->val_) / static_cast<int>(2));
}
// Float specialization
template<>
float halve<float>()
{
return (static_cast<float>(this->val_) / static_cast<float>(2));
}
private:
T val_;
};
int main()
{
Test<int> t1(5);
float f = t1.halve<float>();    // Returns 2.5
int i = t1.halve<int>();        // Returns 2
void* v = t1.halve<void*>();    // Throws. Type void* is not specialized in the class
printf("%.5f %dn", f, i);
getchar();
return 0;
}

最新更新