0

I think it's not possible but someone must know better...

template<typename T>   
T Read()   //T is int, char, etc
{
    return read<T>();
}

template<typename T, Size> 
std::array<T,Size> Read<std::array<T, Size>>()
{
     return unique_read<T, Size>();
}

I guess as soon as I specify any template argument it's no longer a full specialization, and partial specialization is not allowed in functions

The only thing I could come up with is:

template<typename T>
struct _dummy
{
    T Read() {
        return T();
    };
};

template<typename T, size_t Size>
struct _dummy<std::array<T, Size>>
{
    using ArrayType = std::array<T, Size>;

    ArrayType Read() {
        return ArrayType();
    };
};
Jarod42
  • 203,559
  • 14
  • 181
  • 302
Gam
  • 1,254
  • 1
  • 9
  • 18
  • 1
    What are you trying to do? Right now you're just showing complicated ways of writing `T{}`. – Barry Mar 24 '16 at 20:47
  • @Barry I want to process all T's one way, except std:.arrays. That's what I'm trying to do. – Gam Mar 24 '16 at 20:48
  • 1
    You probably want to make your `Read` static inside the `_dummy`, but other than that, this is a trick for partial function specialization. – SergeyA Mar 24 '16 at 20:50
  • @SergeyA The read function is in a class, so I guess I'd have to modify read to take a pointer to the outer class every time it's called and make it static, or create a _dummy object in my class and pass the pointer to the outer class only once. I wanted to avoid both things : – Gam Mar 24 '16 at 21:04

2 Answers2

3

You should use tag dispatching for this sort of job:

namespace detail {
template<class T>struct tag{};

template<class T>
T Read(tag<T>) {
    return T{};
}

template<class T, std::size_t N>
std::array<T, N> Read(tag<std::array<T, N>>) {
    return {1,2,3};
}
}

template<class T>
auto Read() {
    return detail::Read(detail::tag<T>());
}

int main() {
    Read<std::array<int,5>>();
}
David G
  • 94,763
  • 41
  • 167
  • 253
  • Thanks, I guess I'll go for that one. I'm guessing since the argument is unnamed, the compiler should be smart enough to inline everything, and not pass any argument. – Gam Mar 24 '16 at 21:13
  • @Phantom Not because it's *unnamed*, no. Because it has trivial special member functions with no side effects. – Barry Mar 24 '16 at 21:21
  • @Phantom, and if you do not want to be at the mercy of the optimizer, you can always replace function argument with template argument and not create any object at all. – SergeyA Mar 24 '16 at 21:24
  • @SergeyA: but then, we are at the same state than start: we cannot partial specialize template function. – Jarod42 Mar 24 '16 at 21:47
  • @Jarod42, don't know what I was thinking. You are right, of course. – SergeyA Mar 24 '16 at 21:55
  • @Barry Thanks for that, for some reason I thought only constructors / destructors could be trivial (silly me). – Gam Mar 24 '16 at 22:07
0

The other way to do this is to defer to a function object:

template<class T> 
struct reader_op {
  T operator()() const { 
    // whatever needs to happen here
  }
};

// partially specialise for array case
template<class T, size_t N> 
struct reader_op<std::array<T, N>> {
  std::array<T, N> operator()() const { 
    // whatever needs to happen here
  }
};

// reader_op class type is now deduced from T
// when T is a std::array, our specialised function object will
// be used
template<typename T>   
T Read()   //T is int, char, etc
{
    return reader_op<T>()();
}
Richard Hodges
  • 68,278
  • 7
  • 90
  • 142