具有不同返回类型的显式特化模板类成员函数

时间:2011-05-16 04:05:58

标签: c++ templates unix

我正在尝试将一些C ++代码从Windows移植到Solaris(Unix)。有一些模板代码需要更改。我使用Solaris的编译器CC,g ++应该有同样的问题。

我有一部分代码引入了一些麻烦。它们简化如下:

#include <exception>
#include <cmath>
#include <string>
#include <iostream>

// define the "not implement" error
class tempException: public std::exception
{
public:
    virtual const char* what() const throw()
    {
        return "not been implemented!";
    }
} nondeferr;

// the template class
template <typename T>
class A
{
public:
    template <typename Val>
    Val getValue(T t) { throw nondeferr; }

    template<>
    double getValue(T t) { return exp( 1.5 * t ); } //Specialize the getValue for double type.
};

// test code
int main()
{
    try
    {
        A<int> testA;

        std::cout << testA.getValue<double>(2) << std::endl;
        std::cout << testA.getValue<std::string>(2) << std::endl;
    }
    catch (tempException& e)
    {
        std::cout << e.what() << std::endl;
    }

return 0;
}

要在UNIX中编译此示例代码,编译错误就会出现,因为显式特化不能在A类范围内。

这里getValue函数只与返回类型不同,所以我们不能使用重载方式修改它。

由于某种原因,不允许将带有简单模板变量T的A类更改为带有双模板变量T和Val的A类。当我们尝试使用这个基础类时,它会引入很多变化。

我可以知道是否有任何解决方案?我目前正在删除getValue函数,将其替换为getDoubleValue ......但这也不是那么好。


对于那些感兴趣的人,现在A级看起来像这样:

template <typename T>
class A
{
public:
    // the Get Value we want
    template <typename R>
    R getValue(T t) { return get_value_impl<R>::apply(*this, t); }

    // the general get value struct
    template<typename R, typename = void>
    struct get_value_impl
    {
        static R apply(A a, T t) { throw nondeferr; }
    };

    // partial specialization, which is allowed in std C++
    template <typename S>
    struct get_value_impl<double, S>
    {
        static double apply(A a, T t) { return exp( 1.5 * t ); }
    };
};

背后的逻辑是标准中不允许显式特化。但是,允许部分专业化。再次感谢Anycorn的精彩解决方案。

2 个答案:

答案 0 :(得分:3)

// the template class
template <typename T>
class A {
    template<>
    double getValue(T t) { return exp( 1.5 * t ); }
};

标准不允许这样做。

做的:

template <typename T>
class A {
    template<class R>
    R getValue(T t) { return get_value_impl<double>::apply(*this, t); }
    template<class R, class = void>
    struct get_value_impl; // specialize this
};

答案 1 :(得分:3)

如果没有专门化周围的类,则不允许专门化成员函数。 Visual Studio允许将其作为扩展名。