【问题标题】:Function overloading with templates - applying enable_if only when alternative function exists使用模板重载函数 - 仅当存在替代函数时才应用 enable_if
【发布时间】:2019-09-22 11:45:30
【问题描述】:

我设法根据对象的等级为std::ostream 重载插入运算符。 我想扩展下面的例子。

当包含A_new.h 时,它包含A.h...在这种情况下,我正在检查对象的等级,我正在调用f_alterantivef_old。按预期工作:)

直接包含A.h时出现问题,那么f()的实例只有一个-f_old

如果只有一个f() 的实例直接通过A.h 包含,那么它应该是所有对象的默认值...(不仅适用于rank > 1,也适用于所有其他对象) 并且低于条件没有意义。

typename std::enable_if <(std::rank<T>::value > 1), int>::type = 0 >

我知道我需要指定检查另一个 f() 是否存在的条件: 类似:

//goal:    typename std::enable_if <((f_alternative_exist == false) || (std::rank<T>::value > 1 && f_alternative_exist == true) ), int>::type = 0 >

我找到了similar question,但我仍然不确定如何使用std::enable_if 进行操作

#include <iostream>
#include <type_traits>
#include <sstream>

class Foo {
};
    //--- alternative header A_new.h
    //#include A.h
    template< class T,
             typename std::enable_if<(std::rank<T>::value == 1), int>::type = 0 >
    void f(std::ostream& os, const T& value)
    //f_alternative 
    {
        os << "alternative function\n";
        os << "rank == 1" << std::endl;
    }
    //----

    //---- old header A.h
    template < class T,
               typename std::enable_if <(std::rank<T>::value > 1), int>::type = 0 >
    //goal:    typename std::enable_if <((f_alternative_exist == false) || (std::rank<T>::value > 1 && f_alternative_exist == true) ), int>::type = 0 >
    void f(std::ostream& os, const T& value)
    //f_old
    {
        os << "old function\n";
        os << "rank > 1" << std::endl;
    }

    template <class T>
    std::ostream& operator<<(std::ostream& os, const T& foo)
    {
        f<T>(os, foo);
        return os;
    }
    //-----

int main()
{
    Foo foo1[5];
    Foo foo2[5][5];

    std::cout << foo1; 
    std::cout << foo2;

    return 0;
}

https://coliru.stacked-crooked.com/a/7f7ef7bda1805a36

您能否告诉我如何指定std::enable_iff() 未超载以及何时应在所有情况下运行时也可以工作?

【问题讨论】:

    标签: c++ templates c++14 sfinae enable-if


    【解决方案1】:

    一个可能的f_alternative_exist 如下

    template <typename T>
    std::false_type f_alternative_exist_f (std::ostream &, T const &, long);
    
    template <typename T>
    auto f_alternative_exist_f (std::ostream & os, T const & t, int)
       -> decltype( f(os, t), std::true_type{} );
    
    template <typename T>
    using f_alternative_exist
       = decltype(f_alternative_exist_f(std::declval<std::ostream &>(),
                                        std::declval<T>(), 0));
    
    template <typename T>
    static constexpr bool f_alternative_exist_v
       = f_alternative_exist<T>::value;
    

    老版本变成了

    template <typename T, 
              std::enable_if_t<(std::rank<T>::value > 1)
                            || (false == f_alternative_exist_v<T>), int> = 0 >
    void f (std::ostream & os, T const &)
     {
       os << "old function\n";
       os << "rank > 1" << std::endl;
     }
    

    以下是完整的编译C++14示例

    #include <iostream>
    #include <type_traits>
    #include <sstream>
    
    class Foo
     { };
    
    template <typename T>
    std::false_type f_alternative_exist_f (std::ostream &, T const &, long);
    
    template <typename T>
    auto f_alternative_exist_f (std::ostream & os, T const & t, int)
       -> decltype( f(os, t), std::true_type{} );
    
    template <typename T>
    using f_alternative_exist
       = decltype(f_alternative_exist_f(std::declval<std::ostream &>(),
                                        std::declval<T>(), 0));
    
    template <typename T>
    static constexpr bool f_alternative_exist_v
       = f_alternative_exist<T>::value;
    
    #if 0 // enable/disable
    template <typename T,
              std::enable_if_t<std::rank<T>::value == 1, int> = 0 >
    void f (std::ostream & os, T const &)
     {
       os << "alternative function\n";
       os << "rank == 1" << std::endl;
     }
    #endif
    
    template <typename T, 
              std::enable_if_t<(std::rank<T>::value > 1)
                            || (false == f_alternative_exist_v<T>), int> = 0 >
    void f (std::ostream & os, T const &)
     {
       os << "old function\n";
       os << "rank > 1" << std::endl;
     }
    
    template <typename T>
    std::ostream& operator<<(std::ostream& os, const T& foo)
     {
       f<T>(os, foo);
       return os;
     }
    
    int main ()
     {
       Foo foo1[5];
       Foo foo2[5][5];
    
       std::cout << foo1; 
       std::cout << foo2;
     }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-07
      • 2018-04-01
      • 2020-06-01
      相关资源
      最近更新 更多