C ++自定义控制台类 - 如何处理“<

问题描述 投票:1回答:1

我在Windows中用C ++编写自定义控制台,希望打印出任何对象或至少处理每个对象。

这是我的WriteLine方法

template<typename T>
inline void WriteLine(const T& t)
{
    std::cout << t << "\n";
}

我有一个基础“对象”类,它有一个重载的<<运算符,如图所示

friend std::ostream& operator<<(std::ostream& stream, const object& object)
{
    stream << object.toString();
    return stream;
}

我的所有课程都应该来自于此。但是,他们是一种检查类是否有一个重载<<运算符的方法,如果不处理它,这就是我的意思。 (伪代码)

template<typename T>
inline void WriteLine(const T& t)
{
    //check if the object has an overloaded << operator  
    if(itdoes){
        //then print as normal
        std::cout << t;
    }
    else {
        //if it hasn't been overloaded, just print the type of the object using <typeinfo>
        std::cout << typeid(T).name()
    }
}

简而言之,我希望代码在类型(T)没有被重载时编译和处理这种情况,而不是抛出编译错误。如果它没有被重载,只需打印出对象类型名称谢谢

c++ console
1个回答
3
投票

您应该能够使用SFINAE和tag dispatch执行此操作:

template <class T, class = void>
struct HasInserter :
  std::false_type
{};

template <class T>
struct HasInserter<T, std::void_t<decltype(std::declval<std::ostream&>() << std::declval<const T>())>> :
  std::true_type
{};


template <class T>
void WriteLine(const T &t, std::true_type)
{
  std::cout << t << '\n';
}

template <class T>
void WriteLine(const T &t, std::false_type)
{
  std::cout << typeid(T).name() << '\n';
};


template <class T>
void WriteLine(const T &t)
{
  WriteLine(t, HasInserter<T>{});
}

这创建了一个辅助特征,它使用SFINAE来区分表达式stream << t是否格式正确。然后WriteLine函数使用该特征进行标签调度。

请注意,std::void_t是C ++ 17的一个特性,但在标准的早期版本中实现它是微不足道的,因此上述解决方案可以在C ++ 11中使用。


正如@mdatsev在评论中指出的那样,如果你正在使用Boost,你不必自己实现这个特性,你可以使用boost::has_left_shift<std::ostream&, const T>代替(用boost::true_type代替std::true_type,同样用false)。

© www.soinside.com 2019 - 2024. All rights reserved.