Reputation: 6959
The following code compiles fine.
#include <iostream>
struct rgb8{
uint8_t r() const {return 0;};
};
template<typename L, typename P>
L pixelToLevel(P p) {
return static_cast<L>(p);
}
template<>
uint8_t pixelToLevel<uint8_t, rgb8>(rgb8 p) { // <---------- line X
return pixelToLevel<uint8_t, uint8_t>(p.r());
}
int main()
{
pixelToLevel<uint8_t>(rgb8());
return 0;
}
But if in line X I change rgb8 p
to const rgb8& p
, it fails to compile.
(The exact compiler error generated depends on whether or not the explicit template argument rgb8
is also changed to const rgb8&
.)
How can I get it to compile if I want to pass p
by reference rather than by value on line X?
Upvotes: 1
Views: 201
Reputation: 173024
You need to change the template parameter in the declaration of specialization, and template argument when calling it too. Otherwise the primary template would be called instead. e.g.
template<>
uint8_t pixelToLevel<uint8_t, const rgb8&>(const rgb8& p) { // <---------- line X
return pixelToLevel<uint8_t, uint8_t>(p.r());
}
then
pixelToLevel<uint8_t, const rgb8&>(rgb8());
EDIT
Given pixelToLevel<uint8_t>(rgb8());
, template argument deduction is performed with primary template and P
is deduced as rgb8
(it won't be deduced as const rgb8&
with current primary template's parameter declaration), then the specialization version won't be called.
You can apply overloading instead of template specialization. e.g.
template<typename L, typename P>
L pixelToLevel(P p) {
return static_cast<L>(p);
}
template<typename L>
L pixelToLevel(const rgb8& p) { // <---------- line X
return pixelToLevel<L, uint8_t>(p.r());
}
Then pixelToLevel<uint8_t>(rgb8());
would select the 2nd overload.
Upvotes: 1
Reputation: 1529
An alternate solution to @songyuanyao's would be
template<typename L, typename P>
L pixelToLevel(const P& p) {
return static_cast<L>(p);
}
Upvotes: 1