防止模板强制方法中的隐式转换
Prevent implicit conversion in template-enforced method
假设我们有这样的东西:
template <class B>
class A
{
void Foo(B& b)
{
b.Bar(0.5);
}
};
class B
{
void Bar(float) {}
void Bar(double) {}
void Bar(int) {}
};
在这段代码中,类型B
必须提供一个方法Bar()
,该方法接受某个积分类型的参数。这里的问题是允许所有三个版本的B::Bar()
。有没有办法只允许这些方法的一个版本,例如,如果B
提供Bar(float)
,则只进行编译?
您可以使用这种(可怕的)技术,如果A
是用没有公共void Foo(float)
成员的类型B
实例化的,则通过尝试从中获取指向成员类型的特定指针,这种技术将导致编译失败。
template <class B>
class A
{
public:
void Foo(B& b)
{
static_cast<void (B::*)(float)>(&B::Bar);
b.Bar(0.5);
}
};
(导致编译失败的演示。)
如果你想实际调用这个方法,那么你需要使用b.Bar(0.5f);
。0.5
是double
文字,而不是float
文字,所以您应该检查以确保它具有正确的成员,但如果它有void Bar(double)
,您无论如何都会调用它。将常数更改为0.5f
可以解决此问题。
请注意,由于获取指针没有任何副作用,并且不会使用结果,因此任何优秀的编译器都会将其作为no-op进行优化。
你也可以走传统的SFINAE路线,这样做:
template <typename T, typename TMethod>
class has_bar_method
{
private:
struct yes { char _; };
struct no { char _[2]; };
template <typename U, TMethod = &U::Bar>
static yes impl(U*);
static no impl(...);
public:
enum { value = sizeof(impl(static_cast<T*>(nullptr))) == sizeof(yes) };
};
像这样使用:
void Foo(T& b)
{
static_assert(has_bar_method<T, void (T::*)(float)>::value,
"T has method void Bar(float)");
b.Bar(0.5f);
}
现在,如果模板未能实例化,我们将收到一条解释原因的好消息:
prog.cpp:25:8:错误:静态断言失败:T的方法为void Bar(float)
(演示)
相关文章:
- 有没有一种方法可以通过"typedef"为重新定义的基本类型定义特征和强制转换运算符
- 将方法转换为调用该方法的成员函子对象会导致崩溃
- 是否有内置方法可以强制转换为不同的基础类型,但保留常量限定符?
- 将复杂的非基元C++数据类型转换为 Erlang/Elixir 格式,以使用 NIF 导出方法
- 从长整整转换为uint64_t的推荐方法是什么?
- 将传入的网络"char*"数据转换为"uint8_t"并返回的安全方法是什么?
- 有没有将变量名称转换为双指针的简短方法?
- 在 C++ 中将整数数组转换为位集表示形式的最佳方法?
- 从基类实例调用派生类方法而不进行强制转换
- C++ 将静态方法转换为简单方法
- 将 malloc 转换为新的正确方法
- C++方法转换为 C#
- C ++基础私有方法在将自身转换为派生类后可以访问吗?
- 通过构造函数方法输出的类到类类型转换是 5500 为什么不是 5555
- 为什么这种转换方法不编译?
- 两个具有转换方法的类
- 传递和强制转换方法指针
- CRTP 向下转换方法调用
- Qt4:QGraphicsScene/View和自定义转换方法
- c++中这两种类型转换方法的区别是什么?