Reputation: 143
I've created a class that has an OpenCV KalmanFilter inside of it (OpenCV 2.4 if anyone's wondering). Without any template parameters, it compiles just fine.
class ClassOkay
{
public:
struct ClassState
{
cv::KalmanFilter kalmanFilter;
double time;
};
void doSomething();
private:
ClassState state;
};
void ClassOkay::doSomething()
{
//Okay
cv::Mat& x = state.kalmanFilter.statePost;
x.at<double>(0) = 5;
//Okay
state.kalmanFilter.statePost.at<double>(0) = 5;
}
Now when I add a template parameter, although here there are no objects with this template typename, it no longer compiles.
template<typename SubState>
class ClassNotOkay
{
public:
struct ClassState
{
cv::KalmanFilter kalmanFilter;
double time;
};
void doSomething();
private:
ClassState state;
};
template<typename SubState>
void ClassNotOkay<SubState>::doSomething()
{
//Okay
cv::Mat& x = state.kalmanFilter.statePost;
x.at<double>(0) = 5;
//Not okay
state.kalmanFilter.statePost.at<double>(0) = 5;
}
The very last line where I try to access statePost, it seems to not recognize it as a cv::Mat. The compiler error is as follows:
../Base.h: In member function ‘void ClassNotOkay<SubState>::doSomething()’:
../Base.h:169:37: error: expected primary-expression before ‘double’
state.kalmanFilter.statePost.at<double>(0) = 5;
^
../Base.h:169:37: error: expected ‘;’ before ‘double’
It seems really weird to me that it no longer understands that at
is a method of statePost
. Any ideas why and how this is happening?
Upvotes: 1
Views: 170
Reputation: 1624
OK, so I'm no expert, but I think I get the gist of what's happening now. Name lookup can be complex in template classes and functions because of the potential for names that are dependent on the template. (I.e., it may be impossible to determine whether a name referenced inside of a template function or class is a type or a template name or neither when it is first parsed.)
As a result, under some circumstances it is necessary to explicitly tell the compiler when a name is a template or type name. In this example, the compiler is not sure how to resolve at<double>
. Presumably, this is because the compiler mistakenly believes that it could depend on the specific template parameter (SubState
). I'm not sure whether that could be considered a bug - it may just be that the compiler is deliberately conservative wrt name lookup.
Anyway, you can resolve the compiler error by explicitly indicating that at<double>
is a template:
state.kalmanFilter.statePost.template at<double>(0) = 5;
Upvotes: 1