开发者

explicit specialization template class member function with different return type

开发者 https://www.devze.com 2023-03-06 15:32 出处:网络
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 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 gen开发者_Python百科eral 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.


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


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

0

精彩评论

暂无评论...
验证码 换一张
取 消