1

Edit: I believe this question has mistakenly been flagged as a duplicate, especially with the given "duplicates". Please see below.

Today I tried (for the first time) to use template function argument deduction.

My goal is to implement a simple status system. The following code (hopefully) shows the important parts (I didn't test it, it's just to illustrate the problem):

class StatusBase
{
    int m_globalStatus;

protected:
    // The module type should be found by template argument deduction
    template <class Module>
    void SetStatus(enum Module::Status localStatus)
    {
        // Do something with Module
        m_globalStatus = SomeOtherModule<Module>::ToGlobal(localStatus);
    }
};

And here is how some class could use the StatusBase class.

class DerivedA : public StatusBase
{
public:
    enum Status {
        OK,
        WARNING,
        ERROR
    };
    DerivedA ()
    {
        SetStatus(OK);           // doesn't work
        SetStatus(DerivedA::OK); // doesn't work
        SetStatus<DerivedA>(OK); // this works
    }
};

Another class would have a different enum:

class DerivedB : public StatusBase
{
public:
    enum Status {
        OTHER_OK,
        OTHER_WARNING
    };
    ...
};

The interesting part is the call to SetStatus. For the first two lines that don't work, the compiler complains that it

couldn't deduce template parameter `Module'

When I explicitly specify the module (as in the third line), the program compiles.

My questions:

  1. Shouldn't the compiler be able to deduce the module type in the first two lines?! Why is it not working as expected?

  2. Is there any way I can simply call SetStatus(OK); without explicitly specifying the Module type? Would it be easier to solve this problem with C++11?

Thanks!

Compiler used is g++ 4.9.2

Edit: I believe the "nondeduced context" from the so called "duplicates" answer1 and answer2 does not apply here.

The classical nondeduced context example from the other cases is this:

template <typename T>
void g(typename Foo<T>::type);

My case is different:

template <typename T>
void SetStatus(enum T::Status localStatus)
  1. There is the chance of ambiguity in the other cases, especially because the type of Foo<T>::type has nothing to do with T itself. This has clearly been pointed out by answer2.

  2. I do not see any chance of ambiguity in my case. If I'm wrong, please prove it by providing an example how my code could lead to ambiguity.

  3. As already pointed out in my comment, I believe that by logic (not by proper use of template argumente deduction semantics, which I obviously did wrong) the compiler could deduce the type.

Please remove the duplicate flag and answer my original questions.

Community
  • 1
  • 1
ChristophK
  • 733
  • 7
  • 20
  • `SetStatus(OK);` is passing an enum, the argument is of type enum and knows nothing about it's wrapping class, there is no way for template argument deduction to figure out you want the wrapping class. – Alexei Barnes Jul 07 '16 at 12:46
  • Thanks. Is it correct to say that by context & logic in this specific case the compiler *could in theory* figure out that the enum argument belongs to class DerivedA and deduce the type, but in practice this is not how template argument deduction is meant to be used? – ChristophK Jul 07 '16 at 13:04

0 Answers0