C++ 根据类型返回一个值

C++ 根据类型返回一个值,c++,templates,c++11,typetraits,C++,Templates,C++11,Typetraits,考虑下面的例子 template<class Type = void> class MyClass { public: double getValue() { // if "Type == void" return _x, if "Type != void" return _y return (/* SOMETHING */) ? (_x) : (_y); } protec

考虑下面的例子

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;
}; 
模板类MyClass
{
公众:
双getValue()
{
//如果“Type==void”返回x,如果“Type!=void”返回y
返回(/*某物*/)?(\ux):(\uy);
}
受保护的:
双x;
静态常数双精度;
}; 
什么是
/*某物*/
条件

如果模板参数无效,我想返回
\ux
,如果不是,则返回
\uy
。如何执行此操作?

首先,您不能返回任何内容,因为函数返回类型为
void
(已修复)

第二,当
Type
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;
}
模板类MyClass
{
公众:
双getValue()
{
返回y;
}
受保护的:
双x;
静态常数双精度;
}; 
模板
内联双MyClass::getValue()
{
返回x;
}

您可以使用动态强制转换来测试类型。如果强制转换为其他类型,则动态强制转换返回空指针

这里有一个例子

SomeClass* somePointer = NULL;

somePointer = dynamic_cast<SomeClass*>(someOtherPointer);

if (somePointer) 
{
    // *someOtherPointer is of type SomeClass
} 
else 
{
    // *someOtherPointer is not of type SomeClass
}
SomeClass*somePointer=NULL;
somePointer=动态_转换(someOtherPointer);
if(somePointer)
{
//*someOtherPointer属于SomeClass类型
} 
其他的
{
//*SomeOther指针不是SomeClass类型
}

您可以使用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;
}; 
模板
类MyClass
{
公众:
std::如果getValue()启用_
{
//如果“Type==void”返回x,如果“Type!=void”返回y
返回x;
}
std::enable_if::value),decltype(_y)>getValue()
{
返回y;
}
受保护的:
双x;
静态常数双精度;
}; 

目前的主要问题是您将
getValue()
定义为返回
void
。 但是让我们跳过这个。 C++中的函数定义需要很好地定义。这意味着它需要具有不可变的返回类型、参数列表和名称。(我相信还有几个属性,但在这里并不是那么重要)

您可以重载函数,这样就有了两个具有不同参数列表的定义,但是对于具有相同名称的所有函数,返回类型必须相同。如果使用模板,可以得到不同的返回类型,返回类型将是模板参数

现在要处理不同的类型,我相信有两种方法。一种是使用模板和专门化

您可以将
getValue()
定义为
template-double-getValue()getValue
的不同分支。在您的示例中,它将是:

//default case
template<typename T>  double MyClass<T>::getValue() { return _y; }
//void case
template<>  double MyClass<void>::getValue() { return _x; }
这完全取决于您是否可以在编译期间确定类型。RTTI方法有其缺点。如果您想要处理更多类型,RTTI允许您通过修改一个函数来实现,而模板方法则需要添加另一个专门化。我想走哪条路取决于个人喜好。。。当涉及到设计时,模板是非常好的


编辑:哎呀。。。我没有注意到您的类是通过
类型
模板化的。因此,这实际上应该使RTTI apporach不成问题。不管怎样,如果有人以唯一的标题来这里,我都会留下答案,因为我相信这仍然是一种有效的方法。

使用SFINAE确保所有的工作都由编译器完成,而使用
typeid
dynamic\u cast
等的其他选项需要一些运行时成本,这是完全不必要的(因为所有信息都在编译时可用)。事实上,对于何时最好地使用这些方法来说,这些都是非常糟糕的例子

一种可能的SFINAE解决方案是

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;
}; 
模板类MyClass
{
公众:
typename std::enable_如果::type
getValue(){return_x;}
typename std::enable_if::value,double>::type
getValue(){return_y;}
受保护的:
双x;
静态常数双精度;
}; 

?很好的解决方案,你能发布所有代码进行编译吗?不能用“g++-std=c++0x”编译它这比投票最多的更容易理解。您将所有东西都放在一个位置,这将引入不必要的运行时开销。由于类型在编译时是已知的,所以最好使用模板。不要忘记专门化的
inline
,因为如果这在头中,所述专门化将导致链接器错误,如果包含在多个翻译单元中。@ildjarn true,忘了这一点。
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;
};