gpt4 book ai didi

c++ - 防止模板强制方法中的隐式转换

转载 作者:行者123 更新时间:2023-11-28 06:36:03 26 4
gpt4 key购买 nike

假设我们有这样的事情:

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(),该方法采用某种整数类型的参数。问题是所有 3 个版本的 B::Bar() 都是允许的。有没有办法只允许这些方法的一个版本,例如,只有在 B 提供 Bar(float) 时才编译?

最佳答案

您可以使用这种(可怕的)技术,如果 A 被实例化为没有公共(public) 的类型 B,这将导致编译失败void Foo(float) 成员,通过尝试从中获取特定的成员指针类型。

template <class B>
class A
{
public:
void Foo(B& b)
{
static_cast<void (B::*)(float)>(&B::Bar);

b.Bar(0.5);
}
};

( Demo of a resulting compilation failure .)

如果你想真正调用这个方法,那么你需要使用 b.Bar(0.5f);0.5 是一个 double 字面量,而不是一个 float 字面量,所以你会检查以确保它有正确的成员,但是如果它有一个void Bar(double) 无论如何你都会调用它。将常量更改为 0.5f 即可解决此问题。

请注意,由于采用指针没有副作用并且不会使用结果,因此任何体面的编译器都会将其优化为空操作。


你也可以像这样走传统的 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: error: static assertion failed: T has method void Bar(float)

( Demo )

关于c++ - 防止模板强制方法中的隐式转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26768721/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com