提问人:kaisong 提问时间:10/31/2023 最后编辑:Nicol Bolaskaisong 更新时间:10/31/2023 访问量:62
解决模板参数包重载歧义问题
Resolve Template Parameter Pack Overload Ambiguity
问:
最小示例
我有以下结构和一些专业:
template<size_t ...Tpar>
struct Base{};
struct X{};
struct Y{};
template<typename T, size_t ...Tpar>
struct Spline: Base<Tpar...>{}; // general type
template<typename T>
struct Spline<T>: Base<>{}; // specialization 1
template<typename T, size_t n>
struct Spline<T,n>: Base<n>{}; // specialization 2
template<size_t ...Tpar>
struct Spline<X,Tpar...>: Base<Tpar...>{}; // specialization 3
template<size_t ...Tpar>
struct Spline<Y,Tpar...>: Base<Tpar...>{}; // specialization 4
每个执行机构都很长,至少可以举个例子。
错误
以下歧义出现(类似地为):X
Y
int main(){
Spline<X,56> sx56; // error: compiler cannot decide between spec. 2 and spec. 3.
}
为什么超载
我有一个客户类代码,它应该产生各种不同的 bahaviours,具体取决于 i) 主要是类型和 ii) 随后其他模板参数的存在和值。我尝试了不同的东西,这似乎对我正在尝试做的事情很方便——直到现在,我希望重新引入专业 3 和 4。Tpar...
我的期望
我预计会使用专业化 3,因为这是一种类型限制,而只是一个数量专业化。X
n
我想要什么
我想声明,在这种情况下将使用专业化 3。由于 3 和 4 的实现是巨大的,我想在某个地方简明扼要地执行此声明。
解决方法
如果及时修复是强制性的,我会使用以下方法:
template<typename T,size_t ...Tpar>
using Spline = std::conditional_t< std::is_value_t<T,X> , Spline_Spec3<Tpar...> , /*...*/ >;
但那将是
- 容易出错
- 难以阅读
- 需要 X 和 Y 的嵌套 std::conditional_t
- 需要重命名专用化类名称
答:
1赞
kaisong
10/31/2023
#1
正如@HolyBlackCat所提议的那样。
#include<iostream>
template<size_t ...Tpar>
struct Base{};
struct X{};
struct Y{};
template<typename T>
concept is_default_floating_point_type = requires(T t){
requires not( std::is_same_v<T,X> or std::is_same_v<T,Y> );
};
template<typename T, size_t ...Tpar>
struct Spline: Base<Tpar...>{}; // general type
template<typename T>
struct Spline<T>: Base<>{}; // specialization 1
template<typename T, size_t n>
requires is_default_floating_point_type<T>
struct Spline<T,n>: Base<n>{}; // specialization 2
template<size_t ...Tpar>
struct Spline<X,Tpar...>: Base<Tpar...>{
Spline(){ std::cout << "hi.\n"; }
}; // specialization 3
template<size_t ...Tpar>
struct Spline<Y,Tpar...>: Base<Tpar...>{}; // specialization 4
int main(){
Spline<X,56> sx56; // now compiler selects specialization 3
}
评论
0赞
HolyBlackCat
11/1/2023
这个概念可以简化为。此外,如果您不介意更笨拙的符号,也可以完全删除该概念:您可以直接在模板中编写条件:.template<typename T> concept is_default_floating_point_type = !(std::is_same_v<T,X> || std::is_same_v<T,Y>);
template <typename T, size_t n> requires(!(std::is_same_v<T,X> || std::is_same_v<T,Y>))
评论
requires
X
Y
static_assert
requires