0

This is a beginner for C++ programming. (and also in English, sorry for my poor English... ToT)

I searched topics related to my question, but I couldn't find them. I hope that this article is not duplicated one.

I'd like to write some class wraps an ostream object to manipulate output for my purpose.

For my studying, I'm trying to design generalized output stream class so that I made a child class inherits the basic_ostream class template.

As you know, the basic_ostream class requires two template variables(In fact, only the first one is mandatory and another has the default value as char_traits<_CharT>).

But, I stuck at making a constructor for my class, to make the compiler deduce the template variables automatically from an argument of the constructor.

Here is a part of my class header:

#include <ostream>

using namespace std;
template <typename _CharT, typename _Traits = char_traits<_CharT>>
class testOStream : public basic_ostream<_CharT, _Traits> {
  public:
    using typename basic_ostream<_CharT,_Traits>::__ostream_type;

    explicit testOStream(__ostream_type& in)
      :__ostream_type (in.rdbuf()), nowStream(in){};

  private:
    __ostream_type &nowStream;
};

I can instantiate above class by explicit designation of template variables as follows.

testOStream<ostream::char_type,ostream::traits_type> test1(std::cout);

However, the following line omits a compile error which is that the template variable deduction has been failed. (with c++17 standard)

testOStream test2(std::cout);

Actually, there are no problems practically. However, I want to deduce the variables automatically. Is there any way to achieve my goal and is it possible to compile the above code with the c++11 standard? I am able to work around this problem by giving up using the basic_ostream class as the parent class. But I want to know a solution and a reason for this error for my studying.

I am looking for your kind answer and if there is a solved question for this problem on the Stack Overflow, I am very sorry for that.

Thank you!

  • 1
    Template deduction is not done for classes, only functions. If you look at the standard classes, the `std::ostream` "class" isn't really a class, it's a type-alias for `std::basic_ostream`. Perhaps you should do something similar, by having a `basic_testostream` and an alias `testostream`? – Some programmer dude Jul 31 '18 at 09:37
  • in c++11 you dont have template parameter deduction for constructors (not sure about later standards) and the typical workaround is to write a small `make_x` helper template function whose parameters can be deduced. Look eg at `std::make_pair` for an example – 463035818_is_not_an_ai Jul 31 '18 at 09:38
  • 1
    @Someprogrammerdude in c++17 you can have template deduction for classes – Tyker Jul 31 '18 at 09:38
  • 2
    Unrelated to your question, but remember that symbols [beginning with an underscore followed by an upper-case letter are reserved for the implementation](http://stackoverflow.com/questions/228783/what-are-the-rules-about-using-an-underscore-in-a-c-identifier). They are used in the standard library because it's part of the implementation, but your class is not so it should not use such symbols. And using the very implementation-specific `__ostream_type` is also wrong. – Some programmer dude Jul 31 '18 at 09:48

2 Answers2

1

in c++17 you can use class deduction guide

template<typename T>
testOStream(T&) -> testOStream<typename T::char_type, typename T::traits_type>;

but this will deduce not only for std::cout but for any std::basic_ostream

live

Tyker
  • 2,971
  • 9
  • 21
0

As mentioned in a comment, class template deduction exists in C++17. But without any deduction guides then (just like for functions) it has to be a direct deduction, not indirect as is the case with std::cout (or any std::basic_ostream derived object).

If you had a constructor taking a _CharT (plain, pointer or reference) argument then it would be possible to deduce the template type, but not now.

Some programmer dude
  • 400,186
  • 35
  • 402
  • 621