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

发布于 2024-11-07 06:33:46 字数 2031 浏览 0 评论 0原文

我正在尝试将一些 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 提供的出色解决方案。

I am trying to port some C++ code from Windows to Solaris(Unix). There are some template code need to be changed. I am using Solaris' compiler CC, g++ should have same issue.

I have a particular part of code introduce some trouble. They are simplified as following:

#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;
}

To compile this sample code in UNIX, the compilation error comes out as the explicit specialization cannot be in the class A scope.

Here the getValue function only different from the return type, so we cannot modify it using the overload way.

And for some reason, change class A with simple template variable T to class A with double template variables T and Val is not allowed. It will introduce a lots of changes when we try to use this basic class.

May I know if there is any solution? I am currently remove the getValue function, replace it as getDoubleValue... But that is not so good too.


For those who interested, now the class A looks like this:

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 ); }
    };
};

The logic behind is explicit specialization is not allowed in standard. However, partial specialization is allowed. Thanks Anycorn again for the splendid solution.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

素衣风尘叹 2024-11-14 06:33:46
// 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
};
// the template class
template <typename T>
class A {
    template<>
    double getValue(T t) { return exp( 1.5 * t ); }
};

This isnt allowed by standard.

do:

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
};
假扮的天使 2024-11-14 06:33:46

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

It is not allowed to specialize a member function without specializing the surrounding class. Visual Studio allows this as an extension.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文