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

C++ member overloads based on existence of template member

我从一些 SFINAE 开始,但我无法完全掌握我想使用它的一些情况。

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

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

我的编译器抛出

error: ‘class cARD’ has no member named ‘member’

在 decltype 行上(即使未定义回退函数)。这似乎与答案 相矛盾,那么定义尾随 return 类型的正确方法是什么?

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

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

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