0

I have the following code (simplified here for readability):

enum id_t {B, C, D};

template <id_t id, int16_t value> class class_name;

template <int16_t value>
class class_name<B, value>
{ 
public:
    void member_func() { /* do something related to B */ }
};

template <int16_t value>
class class_name<C, value>
{ 
public:
    void member_func() { /* do something related to C */ }
};

template <int16_t value>
class class_name<D, value>
{ 
public:
    void member_func() { /* do something related to D */ }
};

The code above works fine. I do something like this and it's ok:

class_name<B, 5> obj_b;
class_name<C, 3> obj_c;
class_name<D, 1> obj_d;

obj_b.member_func();
obj_c.member_func();
obj_d.member_func();

I also need to instantiate class_name as argument to functions, and it works, despite the ugly syntax:

do_something_with_class_name_objs(class_name<D, 0>(), class_name<C, 2>());

Because I want the things as easy as possible, to other people to use, I was trying to make the template arguments implicit, just like we do when we call function templates with arguments and the compiler knows how it need to instantiate that function just looking at the function arguments, not the template ones.

I want to instantiate my class_name this way:

class_name obj_b(B, 5);
class_name obj_c(C, 3);
class_name obj_d(D, 1);

So I could be able to instantiate it as argument to functions this way:

do_something_with_class_name_objs(class_name(D, 0), class_name(C, 2));

It is much more readable, IMHO.

I have tried to do change my template specializations in some ways. None of the constructors in the following template worked:

template <int16_t value>
class class_name<B, value>
{ 
public:
    class_name(id_t id, int16_t value) {}           // don't work
    class_name(B, value) {}                         // don't work
    class_name<B, value>(id_t id, int16_t value) {} // don't work  
    void member_func() { /* do something related to B */ }
}; 

What is the right way to do that?

  • Your best bet is to wait for C++17 where this will likely work. See [proposal P0091R3](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0091r3.html) – Bo Persson Dec 24 '16 at 10:55
  • 1
    `class_name obj_q(rand() > 42 ? B : C, 5);` // What's the type of `obj_q`, `class_name` or `class_name`? – cpplearner Dec 24 '16 at 11:15
  • You may introduce something like `#define ClassName(ID, N) class_name()` to have your expected syntax, but the syntax with `<>` is clearer for me (as I understand than parameters should be constexpr). – Jarod42 Dec 24 '16 at 11:34
  • @BoPersson, good to know. –  Dec 24 '16 at 15:45
  • Thanks, @Jarod42. I'll use your solution while C++17 does not arrive. –  Dec 24 '16 at 15:46
  • @cpplearner, I didn't understand your question. –  Dec 24 '16 at 15:47

1 Answers1

1

The template arguments of a class template cannot be deduced from a constructor call... until the upcoming C++17 standard. See Class template deduction.

eerorika
  • 232,697
  • 12
  • 197
  • 326