Reputation: 43179
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?
Upvotes: 0
Views: 430
Reputation: 609
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]
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.
Upvotes: 1
Reputation:
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);
}
Upvotes: 0
Reputation: 10665
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)
Upvotes: 1