13

I have reproduced with a simple code below something I am missing.
Class B owns class A as member and uses same typenames .
I want to avoid replicating these templates so that in the main() I can call something like B b(a, 3.0) which would reuse template from A. Is that possible ?

#include <iostream>
#include <vector>

template<int N, typename T=double>
struct A
{
    A(T val) : vecA(N, val) {}
    void print() { for (auto i : vecA) std::cout << i << ";"; }
    std::vector<T> vecA;
};

template<int N, typename T>
struct B
{
    B(const A<N,T> & in, T scal) : a(in), scalB(scal) {}
    void print() { a.print(); std::cout << " | " << scalB << std::endl; }
    A<N,T> a;
    T scalB;
};


int main()
{
    A<5,float> a(2.0);
    B<5,float> b(a, 3.0);   // This is redundancy. Can I do something like B b(a,3.0) ?
    b.print();
}
coincoin
  • 4,595
  • 3
  • 23
  • 47
  • 2
    If you are courious about why it is not allowed: http://stackoverflow.com/questions/984394/why-not-infer-template-parameter-from-constructor – DarioP Dec 17 '14 at 16:56

3 Answers3

16

Template parameters can be deduced from the types of a function template's arguments, but not of a class template's constructor arguments. So you could do what the standard library does (for example with make_pair) and write a function to deduce them for you:

template <int N, typename T>
B<N,T> make_b(const A<N,T> & in, T scal) {
    return B<N,T>(in, scal);
}

auto b = make_b(a, 3.0f);

Note that this requires a float argument 3.0f, to match the type of a. You could parametrise that type separately, if you want to allow conversions on the second argument:

template <int N, typename T, typename T2>
B<N,T> make_b(const A<N,T> & in, T2 scal) {
    return B<N,T>(in, scal);
}

auto b = make_b(a, 3.0);
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
8

No, since you create object of type B<int, T>. With C++11 you can use auto and write simple creation function

template<int N, typename T>
B<N, T> create(const A<N, T>& in, T scal)
{
   return B<N, T>(in, scal);
}

// in main
auto b = create(a, 3.0f);
ForEveR
  • 55,233
  • 2
  • 119
  • 133
2

Not in this world.

auto b = make_b(a, 3.0);

(Implementation of make_b left as an exercise; refer to std::make_pair).

Bartek Banachewicz
  • 38,596
  • 7
  • 91
  • 135
  • 5
    `make_pair` or `make_tuple` would be better examples. `make_shared` and `make_unique` don't deduce their return types. – Mike Seymour Dec 17 '14 at 10:36