英文:
Select which member function to call at compile time
问题
我有一个在某个对象 `T` 上的模板类。`T` 定义了两个成员函数 `bar` 和 `foo`。
```cpp
template<class T>
class A {
public:
void f() {
t_.bar();
t_.foo();
}
private:
T t_;
};
现在我想要能够在构造时(理想情况下是在编译时)告诉 A
调用 foo
或 bar
中的一个,而不是两者都调用。因此,构造时的想法是告诉 A
调用 T
的哪个成员函数。
我目前采用的解决方案是在 A
的构造函数中传递一个可调用对象 void callMember(const T& t) { return t.foo(); }
,以在运行时调用正确的成员函数,但我想知道是否有更好的解决方案?
<details>
<summary>英文:</summary>
I have a templated class on some object `T`. `T` defines two member functions `bar` and `foo`
template<class T>
class A {
public:
void f() {
t_.bar();
t_.foo();
}
private:
T t_;
};
Now I would like be able to tell `A` (ideally at compile time), to call either `foo` or `bar`, but not both. So the idea is to tell A at construction time which member function of `T` to call.
The solution I have currently in place is to pass a callable `void callMember(const T& t) { return t.foo(); }` in `A`'s constructor to at runtime call the right member, but I'm wondering if there is a better solution?
</details>
# 答案1
**得分**: 1
以下是您要翻译的内容:
You can add a `bool` template parameter to `A` that tells it which member function of `T` to call, and then use a `constexpr if` on that parameter in the body of `f`:
```cpp
template<class T, bool Choice>
class A {
public:
void f() {
if constexpr(Choice) // doesn't strictly have to be constexpr
// if T defines both bar and foo
t_.bar();
else
t_.foo();
}
private:
T t_;
};
Now for some type like:
struct S {
void bar() { std::cout << "bar"; }
void foo() { std::cout << "foo"; }
};
you can do:
A<S, true> a;
a.f(); // calls S::bar
A<S, false> b;
b.f(); // calls S::foo
Here's a demo.
英文:
You can add a bool
template parameter to A
that tells it which member function of T
to call, and then use a constexpr if
on that parameter in the body of f
:
template<class T, bool Choice>
class A {
public:
void f() {
if constexpr(Choice) // doesn't strictly have to be constexpr
// if T defines both bar and foo
t_.bar();
else
t_.foo();
}
private:
T t_;
};
Now for some type like:
struct S {
void bar() { std::cout << "bar"; }
void foo() { std::cout << "foo"; }
};
you can do:
A<S, true> a;
a.f(); // calls S::bar
A<S, false> b;
b.f(); // calls S::foo
Here's a demo.
答案2
得分: 0
我假设可以根据调用的方法来实例化A
的不同类型。如果是这种情况,我建议选择两种类型而不是两种方法。
假设X
是具有这两种方法的类型,那么你可以这样做:
struct X {
void foo() {}
void bar() {}
};
struct Xfoo {
X x;
void foobar() { x.foo(); }
};
struct Xbar {
X x;
void foobar() { x.bar(); }
};
现在模板如下所示:
template<class T>
class A {
public:
void f() {
t_.foobar();
}
private:
T t_;
};
然后,你可以实例化A<Xfoo>
或A<Xbar>
,而不是A<X>
。
我假设你可能有不止一种类型X
,那么Xfoo
和Xbar
可以根据要包装的类型进行参数化。
英文:
I assume its Ok to have instantiations of A
be of different type depending on which method is called. If that is the case I suggest to choose between two types rather than two methods.
Say X
is the type with the two methods, then you can do this:
struct X {
void foo() {}
void bar() {}
};
struct Xfoo {
X x;
void foobar() { x.foo(); }
};
struct Xbar {
X x;
void foobar() { x.bar(); }
};
Now the template is:
template<class T>
class A {
public:
void f() {
t_.foobar();
}
private:
T t_;
};
And you either instantiate A<Xfoo>
or A<Xbar>
rather than A<X>
.
I suppose you have more than just one type X
, then Xfoo
and Xbar
can be parametrized on the type to be wrapped.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论