3

考虑以下示例

template<class Type = void> class MyClass
{
    public:
        double getValue()
        {
            // if "Type == void" return _x, if "Type != void" return _y
            return (/* SOMETHING */) ? (_x) : (_y);
        }
    protected:
        double _x;
        static const double _y;
}; 

可能是什么/* SOMETHING */条件?

_x如果模板参数为void,我想返回,_y如果不是,则返回。怎么做 ?

4

5 回答 5

12

首先,你不能返回任何东西,因为函数返回类型是void.(固定的)

其次,您可以专门化该函数以在Typeis时采取不同的行动void

template<class Type> class MyClass
{
    public:
        double getValue()
        {
            return _y;
        }
    protected:
        double _x;
        static const double _y;
}; 

template<>
inline double MyClass<void>::getValue()
{
   return _x;
}
于 2012-09-26T09:09:54.560 回答
4

您可以使用 SFINAE 编写:

template<typename Type = void>
class MyClass
{
public:
    std::enable_if<std::is_same<Type, void>::value, decltype(_x)> getValue()
    {
        // if "Type == void" return _x, if "Type != void" return _y
        return _x;
    }
    std::enable_if<!(std::is_same<Type, void>::value), decltype(_y)> getValue()
    {
        return _y;
    }
protected:
    double _x;
    static const double _y;
}; 
于 2012-09-26T09:31:08.477 回答
0

您可以使用动态转换来测试类型。如果转换为不同的类型,则动态转换返回空指针;

这是一个例子。

SomeClass* somePointer = NULL;

somePointer = dynamic_cast<SomeClass*>(someOtherPointer);

if (somePointer) 
{
    // *someOtherPointer is of type SomeClass
} 
else 
{
    // *someOtherPointer is not of type SomeClass
}
于 2012-09-26T09:16:10.623 回答
0

For now main problem is that you defined getValue() as returning void. But let's skip that. A function definition in C++ needs to be well defined. This means it needs to have immutable return type and argument list and a name. (There is couple of more attributes I believe but it is not that important here).

You can overload function so you have a couple of definitions with differing argument lists, however the returning type must be the same for all functions with the same name. You can get different returning type if you use templates, and the returning type would be a template argument.

Now to handle different types, there are two ways I believe. One is use templates and specializations.

You could define getValue() as template<T> double getValue(); and then use different specializations to handle different branches of your original getValue. In your example it would be:

//default case
template<typename T>  double MyClass<T>::getValue() { return _y; }
//void case
template<>  double MyClass<void>::getValue() { return _x; }

The second option is to use RTTI mechanism which allows to determine types of objects in run-time. The the code could like almost exactly like yours. E.g.

    double getValue()
    {
        // if "Type == void" return _x, if "Type != void" return _y
        return (typeid(Type) == typeid(void)) ? (_x) : (_y);
    }

It all depends whether you can determine Type during compilation or not. The RTTI approach has its drawbacks. If you ever wanted to handle more types RTTI allows you to do it by modifying one function while template approach you would need to add another specialization. I guess its up to one's preferences which path to take... and template are quite nicer when it comes to design.

Edit: Oopsies ... I missed that your class is templatized by the Type. So that should practically remove RTTI apporach out of question. I will leave the answer anyways if anyone ever comes here drawn by the sole title, as I believe it is still a valid way to do it.

于 2012-09-26T09:34:44.893 回答
0

Using SFINAE ensures that all the work is done by the compiler, while other options using typeid, dynamic_cast etc, require some run-time costs, which are completely unnecessary (since all the information is available at compile time). In fact, these are extremely bad examples for when best to use such methods.

A possible SFINAE solution is

template<class Type = void> class MyClass
{
public:
    typename std::enable_if< std::is_void<Type>::value, double>::type
    getValue() { return _x; }
    typename std::enable_if<!std::is_void<Type>::value, double>::type
    getValue() { return _y; }
protected:
    double _x;
    static const double _y;
}; 
于 2012-09-26T13:07:32.310 回答