基于模板成员的存在,C ++成员重载

时间:2018-05-22 11:57:01

标签: c++ templates sfinae

我一直在使用一些SFINAE,但我无法处理一些我想用它的情况。

例如,如果我有一个基于模板的类,它应该根据模板参数具有不同的函数实现,即

template <typename T>
class cExampleClass
{
     /// Function enabled when "cExampleClass::member" exists
     auto overloadedFunction() -> decltype((std::declval<t>().member()),T::some_dependant_type())
     {
           // Do some stuff and use cExampleClass::member
     }

     /// Function enabled when "cExampleClass::member" does not exist
     auto overloadedFunction() -> T::some_dependant_type()
     {
           // Do some different stuff
     }
};

将函数称为

是理想的
object.overloadedFunction();

我的编译器抛出

  

错误:'class cARD'没有名为'member'的成员

decltype行上的

(即使未定义回退功能)。这似乎与答案here相矛盾,那么定义尾随返回类型的正确方法是什么?

此外,该功能显然不能超载。有没有简单的方法来定义回退函数?

1 个答案:

答案 0 :(得分:1)

您有一个硬错误,因为您的方法不是模板,请将其更改为:

template <typename U>
class cExampleClass
{
     /// Function enabled when "cExampleClass::member" exists
     template <typename T = U>
     auto overloadedFunction()
     -> decltype((std::declval<T>().member()),T::some_dependant_type())
     {
           // Do some stuff and use cExampleClass::member
     }

     /// Function enabled when "cExampleClass::member" does not exist
     template <typename T = U>
     auto overloadedFunction() -> decltype(T::some_dependant_type())
     {
           // Do some different stuff
     }
};

但是你有问题,因为这个方法对于符合这两个条件的类型都是不明确的。

添加标签以排序重载是可能的:

template <std::size_t I>
struct overload_tag : overload_tag<I - 1> {};

template <>
struct overload_tag<0> {};

然后

template <typename U>
class cExampleClass
{
private:
     /// Function enabled when "cExampleClass::member" exists
     /// Preferred function
     template <typename T = U>
     auto overloadedFunction(overload_tag<1>)
     -> decltype((std::declval<T>().member()),T::some_dependant_type())
     {
           // Do some stuff and use cExampleClass::member
     }

     /// Function enabled when "cExampleClass::member" does not exist
     template <typename T = U>
     auto overloadedFunction(overload_tag<0>) -> decltype(T::some_dependant_type())
     {
           // Do some different stuff
     }
public:
     template <typename T = U>
     auto overloadedFunction() -> decltype(overloadedFunction(overload_tag<1>{}))
     {
          return overloadedFunction(overload_tag<1>{});
     }
};