问题
Consider the following code:
#include <iostream>
#include <type_traits>
struct A;
template<class T>
concept HasParent = std::is_convertible_v<typename T::parent*, A*>;
struct A{};
struct B : A { using parent = A; };
template<class T> int foo(T*) { return 1; }
template<HasParent T> int foo(T*)
{
// call the other one?
return 2;
}
int main()
{
B b;
std::cout << foo(&b) << std::endl; // displays 2
return 0;
}
Is it possible to call the general foo<T>(T*)
function from foo<HasParent T>(T*)
?
(this is a (functional) example, but I can link the complete code on github)
回答1:
Is it possible to call the general
foo<T>(T*)
function fromfoo<HasParent T>(T*)
?
You need some way to differentiate between the two functions in order to do this.
For example:
template <typename T> void foo(T);
template <typename T> requires true auto foo(T) -> int;
The second one is obviously more constrained than the first, for all T
, so foo(42)
calls the second. But, you can differentiate between the two:
auto unconstrained = static_cast<void(*)(int)>(foo);
Here, the constrained function template returns int
so it's not a viable candidate and we get the unconstrained one instead.
In your example, both return int
, so this particular trick doesn't work. But the key is that you need some way to differentiate the two templates.
A better way is probably:
template <typename T, std::monostate M = {}>
void foo(T);
template <typename T> requires true
void foo(T arg) {
foo<T, std::monostate{}>(arg); // calls the unconstrained one
}
Using monostate
here is kinda cute since it doesn't actually change the number of template instantiations (there's only one monostate
... ). foo(42)
calls the second, which calls the first. Demo.
But it might be better to just add a new function and have both the unconstrained and constrained version of the function template invoke that one (in the sense that it's arguably less cryptic than the monostate
approach).
来源:https://stackoverflow.com/questions/61176476/call-less-constrained-functionally-equivalent-function