Reputation: 305
Today I write the code below with a mistake:
template<int V>
typename std::enable_if<(V > 0)>::type
Test() {
Test<V - 1>();
}
template<int V>
typename std::enable_if<(V == 0)>::type
Test() {
std::cout << "0" << std::endl;
}
int main() {
Test<1>();
}
The compiler errored my that no matching function for call to ‘Test<(1 - 1)>()’
, I checked and found that I should put the std::enable_if<(V == 0)>::type
version first, or , I use forward declaration like this:
// forward declaration
template<int V>
typename std::enable_if<(V == 0)>::type
Test();
template<int V>
typename std::enable_if<(V > 0)>::type
Test() {
Test<V - 1>();
}
template<int V>
typename std::enable_if<(V == 0)>::type
Test() {
std::cout << "0" << std::endl;
}
int main() {
Test<1>();
}
The I noticed that when I write code using partial specialization, I never met this problem before, for example:
template <int V, typename = void>
struct Foo {
static void Test() {
std::cout << V << std::endl;
Foo<V - 1>::Test();
}
};
template <int V>
struct Foo <V, typename std::enable_if<V == 0>::type> {
static void Test() {
std::cout << "0" << std::endl;
}
};
int main() {
Foo<1>::Test();
}
this code works find and I didn't use forward declaration, so here's my question:
Why the function version cannot "see" functions declarations after itself, while the struct version knows? Did SFINAE happened in the function version's compilation?
P.S. Here's the error message using clang, which seems more specific:
/home/liu/source/untitled4/main.cpp:7:3: error: call to function 'Test' that is neither visible in the template definition nor found by argument-dependent lookup
Test<V - 1>();
And here's the error message I mentioned in my question using GCC:
/home/liu/source/untitled4/main.cpp:7:14: error: no matching function for call to ‘Test<(1 - 1)>()’
Test<V - 1>();
And I don't have a Windows environment on my hand for now, I'll paste the error later if MSVC reports errors.
Upvotes: 4
Views: 308
Reputation: 39993
While the comments have addressed the problem—that each independent function template must be declared before use—the question about the difference can be answered simply by quoting [temp.class.spec.general]/7:
Partial specialization declarations themselves are not found by name lookup. Rather, when the primary template name is used, any previously-declared partial specializations of the primary template are also considered. […]
As such, it is the specializations that are reachable from the point of instantiation that are available, and so mutual references may be made freely prior to any instantiation. (This is akin to the rule for lookup for dependent function names.)
Upvotes: 1