禁止显式指定的模板
Disallow templates that are explicitly specified
我想要一个宽模板,除了我明确指定了大小写时,它"做任何需要做的事情"。
具体来说,我正在重载operator()
以将其用于多维矩阵的矩阵索引。我还想允许使用迭代器指定任意数量的索引。理想情况下,我将具有以下签名:
operator()(size_t);
operator()(size_t,size_t);
operator()(size_t,size_t,size_t);
...
template<class Iterator> operator()(Iterator,Iterator);
问题是永远不会达到operator()(size_t,size_t)
,因为编译器也能够模板template<class Iterator> operator()(Iterator,Iterator)
。我怎样才能避免这种情况?
一个明显的解决方案是使用std::vector<size_t>::iterator
而不是Iterator
.我已经尝试过这个,但这缩小了其他地方的使用范围。
一个最小的例子:
#include <iostream>
class Foo
{
private:
double data[9];
public:
Foo(){};
double& operator()(size_t i, size_t j)
{
std::cout << "operator()(size_t i, size_t j)" << std::endl;
return data[0];
}
template<class Iterator>
double& operator()(Iterator first, Iterator last)
{
std::cout << "operator()(Iterator first, Iterator last)" << std::endl;
return data[0];
}
};
int main()
{
Foo bar;
bar(0,1);
}
输出:
operator()(Iterator first, Iterator last)
而我希望这种情况输出
operator()(size_t i, size_t j)
几乎可以肯定的是,通过重载分辨率选择模板的原因是您传入的两个参数并不是真正size_t
。他们可能是int
,或者别的什么。如果它们真的是size_t
,那么我希望你的非模板重载被选中。清理它应该使事情正常工作,按原样,但它足够简单,在任何情况下都可以使它工作。
在这种情况下,通常的方法是在传入参数size_t
时,使用 SFINAE 排除模板参与重载解析。类似于(使用 C++17):
template<class Iterator,
typename=std::enable_if_t<
std::negation_v<std::is_integral_v<Iterator>>>> operator()(Iterator,Iterator)
{
// ...
}
这是你的起点。使用std::is_same_v<Iterator,size_t>
很诱人,但您很快就会发现,这只有在您正好传入size_t
时才有效。如果你不小心,int
很容易溜进去,在这种情况下,这会分崩离析。所以你可能需要使用std::is_integral_v
.希望您不会在任何地方传递浮点值,并依赖于将它们截断为下一个最接近的整数值。如果你这样做,你将不得不进一步调整。
std::is_integral_v
和std::enable_if_t
快捷方式仅在 C++17(以及std::void_t
)中可用,但如有必要,可以在早期标准中重新发明该轮子。
您也可以尝试在相反的方向上使用 SFINAE:仅当Iterator
解析为std::iterator_traits
识别的内容时,才让此模板参与重载解析。最佳方法取决于您特定类的要求。
- ISO C++禁止声明没有类型的"setInputNombre"
- 禁止显示由于常量为零而比较始终为假的警告
- 禁止在控制台上记录谷神星
- 禁止显示有关包含文件中 #pragma 包的警告
- 禁止指针和整数之间的比较C++
- ISO C++禁止指针和整数 [-fpermissive] [c++] 之间的比较
- 为什么我会收到此警告:ISO c++ 禁止可变长度数组"v"[-Wvla]
- 当空基类也是成员变量时,为什么禁止空基优化?
- ISO 中禁止可变长度数组 C++崇高文本中的错误 3.
- 标记类以禁止操作
- 禁止子函数调用父级的抽象(或虚拟)函数
- Linux C 只禁止我的程序使用核心转储
- 错误:ISO C++禁止可变长度数组"subVec"[-Werror=vla]
- 如何禁止在 g++ 中使用但从未定义警告的内联函数
- 捕获/禁止发送到 std::cout 的 OpenCV 警告
- Qt 错误 iso c++ 禁止指针和整数之间的比较 -permissive
- 为什么禁止建造 istreams?
- 是否可以禁止在for循环体内部修改循环变量
- 在c++中,如果首先禁止默认构造,那么禁止复制构造有意义吗
- 禁止复制构造函数和赋值运算符singleton类