Reputation: 1449
In my code I use a templated image class Image<T>
in combination with std::shared_ptr
. These image pointers are supposed to be passed to various image processing functions, some of which are independent of the image type. Consider the following definition of Image<T>
, and two processing functions function1()
and function2()
.
#include <memory>
template <typename T>
struct Image
{
typedef std::shared_ptr<Image<T>> Ptr;
};
template <typename T>
void function1 (typename Image<T>::Ptr image) {}
template <typename T>
void function2 (std::shared_ptr<Image<T>> image) {}
While function1()
and function2()
effectively have the same signature, function1()
is easier to read and hides the details of how the pointer is realized. However, I am having trouble calling function1()
without explicitly specifying the template type. Consider the following code:
int main (void)
{
Image<int>::Ptr image = std::make_shared<Image<int>>();
function1(image); // Does NOT compile
function1<int>(image); // Does compile
function2(image); // Does compile
return 0;
}
Where the first call leads to the compile error:
example.cc: In function 'int main()':
example.cc:18:19: error: no matching function for call to 'function1(MyClass<int>::Ptr&)'
example.cc:18:19: note: candidate is:
example.cc:10:6: note: template<class T> void function1(typename MyClass<T>::Ptr)
example.cc:10:6: note: template argument deduction/substitution failed:
example.cc:18:19: note: couldn't deduce template parameter 'T'
My question is the following: Is it possible to use the signature of function1()
without having to manually specify the template argument? What is causing the compiler error?
I suspect the problem is caused by the fact that Image<T>::Ptr
is a dependent type. Thus the compiler cannot know the exact definition of this field at compile time. Is it possible to tell the compiler there will be no specializations of this field, in the spirit of the typename
keyword which tells the compiler that a field is a type?
Upvotes: 10
Views: 562
Reputation: 60999
What is causing the compiler error?
You're (solely) using T
in a non-deduced context: nested-name-specifiers. That is, you put T
inside a name that merely specifies where the type lies within. The compiler cannot understand your actual intention and would have to try a lot of T
's.
Is it possible to use the signature of
function1()
without having to manually specify the template argument?
Not really. If you want a more concise way of referring to a smart pointer to an Image, you can use an alias template though:
template <typename T>
using ImagePtr = std::shared_ptr<Image<T>>;
And write function1
thusly:
template <typename U>
void function1(ImagePtr<U> p) {}
Upvotes: 9