调用约束较少的功能等效函数
Call less constrained functionally equivalent function
考虑以下代码:
#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;
}
是否可以从 foo<HasParent T>(T*)
调用通用 foo<T>(T*)
函数?
(这是一个(功能)示例,但我可以 link github 上的完整代码)
Is it possible to call the general foo<T>(T*)
function from foo<HasParent T>(T*)
?
您需要一些方法来区分这两个函数才能做到这一点。
例如:
template <typename T> void foo(T);
template <typename T> requires true auto foo(T) -> int;
对于所有T
,第二个显然比第一个更受约束,所以foo(42)
调用第二个。但是,您可以区分两者:
auto unconstrained = static_cast<void(*)(int)>(foo);
在这里,约束函数模板 returns int
所以它不是一个可行的候选者,我们改为使用不受约束的模板。
在你的例子中,return int
,所以这个特殊的技巧不起作用。但关键是你需要一些的方式来区分这两个模板。
更好的方法可能是:
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
}
在这里使用 monostate
有点可爱,因为它实际上并没有改变模板实例化的数量(只有一个 monostate
... )。 foo(42)
调用第二个,调用第一个。 Demo.
但最好只添加一个新函数,并让函数模板的不受约束和受约束版本都调用该函数模板(从某种意义上说,它可以说比 monostate
方法更隐蔽)。
考虑以下代码:
#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;
}
是否可以从 foo<HasParent T>(T*)
调用通用 foo<T>(T*)
函数?
(这是一个(功能)示例,但我可以 link github 上的完整代码)
Is it possible to call the general
foo<T>(T*)
function fromfoo<HasParent T>(T*)
?
您需要一些方法来区分这两个函数才能做到这一点。
例如:
template <typename T> void foo(T);
template <typename T> requires true auto foo(T) -> int;
对于所有T
,第二个显然比第一个更受约束,所以foo(42)
调用第二个。但是,您可以区分两者:
auto unconstrained = static_cast<void(*)(int)>(foo);
在这里,约束函数模板 returns int
所以它不是一个可行的候选者,我们改为使用不受约束的模板。
在你的例子中,return int
,所以这个特殊的技巧不起作用。但关键是你需要一些的方式来区分这两个模板。
更好的方法可能是:
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
}
在这里使用 monostate
有点可爱,因为它实际上并没有改变模板实例化的数量(只有一个 monostate
... )。 foo(42)
调用第二个,调用第一个。 Demo.
但最好只添加一个新函数,并让函数模板的不受约束和受约束版本都调用该函数模板(从某种意义上说,它可以说比 monostate
方法更隐蔽)。