Question

In C++03, I have the following code built with gcc v3.4.6 for which I don't understand why calling _setValueSafeFails() get a compiler error where as calling the similar _incrValueSafe() does not.

Test.h:

class Test
{
public:
  void test();

  template<typename T> void _incrValueSafe(T &value) {
    ++value;
  }

  template<typename T> void _setValueSafeFails(T &value, const T setVal) {
    value = setVal;
  }

  template<typename T> void _setValueSafeWorks(volatile T &value, const T setVal) {
    value = setVal;
  }

  volatile bool _testValue;

};

Test.cpp:

#include "Test.h"

void Test::test() {
  _incrValueSafe(_testValue);
  _setValueSafeFails(_testValue, true);
  _setValueSafeWorks(_testValue, true);
}

Test.cpp: In member function `void Test::test()':
Test.cpp:5: error: no matching function for call to `Test::_setValueSafeFails(volatile bool&, bool)'

Shouldn't _incrValueSafe() get the same error since there is no volatile in its signature either? How are these two treated differently, or is this just a compiler bug?

Was it helpful?

Solution

As others have explained, binding the first parameter to _testValue implies that T is volatile bool, whereas binding the second parameter to true implies that T is merely bool (without the volatile modifier). The clang compiler gives a nice diagnostic:

clang++ -o main  -std=c++1y -pedantic -Wall -stdlib=libc++ main.cpp -stdlib=libc++
main.cpp:26:5: error: no matching member function for call to '_setValueSafeFails'
    _setValueSafeFails(_testValue, true);
    ^~~~~~~~~~~~~~~~~~
main.cpp:12:35: note: candidate template ignored: deduced conflicting types for parameter 'T' ('volatile bool' vs. 'bool')
        template<typename T> void _setValueSafeFails(T &value, const T setVal) {
                                  ^
main.cpp:9:13: warning: incrementing expression of type bool is deprecated [-Wdeprecated-increment-bool]
            ++value;
            ^ ~~~~~
main.cpp:25:5: note: in instantiation of function template specialization 'Test::_incrValueSafe<volatile bool>' requested here
    _incrValueSafe(_testValue);
    ^
1 warning and 1 error generated.
make: *** [main] Error 1

Regarding leading underscores: I just avoid them, partly to avoid debates about what is or isn't strictly legal. I prefer the popular convention: prefix private variables with m_, and don't decorate private function names in any special way. (Leading underscores are de rigeur for private members in Python, but of course, C++ is a very different language.) For the record, the holy standard says the following:

17.6.4.3.2 Global names [global.names]


  1. Certain sets of names and function signatures are always reserved to the implementation:

    — Each name that contains a double underscore __ or begins with an underscore followed by an uppercase letter (2.12) is reserved to the implementation for any use.

    — Each name that begins with an underscore is reserved to the implementation for use as a name in the global namespace.

OTHER TIPS

typename T for _incrValueSafe is volatile bool

Because

template<typename T> void _setValueSafeFails(T &value, const T setVal) {
    value = setVal;
}

would be instanciated to:

void _setValueSafeFails(volatile bool &value, const volatile bool setVal)

The type volatile bool and bool are different types and lead to the mismatch in _setValueSafeFails.

You may do:

class Test
{
public:
  void test();
  template<typename T, typename U> void _setValueSafeA(T &value, const U setVal) {
    value = setVal;
  }
  template<typename T> void _setValueSafeB(T &value, const T& setVal) {
    value = setVal;
  }

  volatile bool _testValue;

};

void Test::test() {
  volatile bool true_value = true;
  _setValueSafeA(_testValue, true);
  _setValueSafeB(_testValue, true_value);
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top