选择在编译时调用哪个成员函数

huangapple go评论66阅读模式
英文:

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 调用 foobar 中的一个,而不是两者都调用。因此,构造时的想法是告诉 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&amp; t) { return t.foo(); }` in `A`&#39;s constructor to at runtime call the right member, but I&#39;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&lt;class T, bool Choice&gt;
class A {
public:
   void f() {
    if constexpr(Choice)  // doesn&#39;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 &lt;&lt; &quot;bar&quot;; }
    void foo() { std::cout &lt;&lt; &quot;foo&quot;; }
};

you can do:

A&lt;S, true&gt; a;
a.f();        // calls S::bar

A&lt;S, false&gt; 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,那么XfooXbar可以根据要包装的类型进行参数化。

英文:

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&lt;class T&gt;
class A {
   public:
   void f() {
       t_.foobar();
   }
   private:
   T t_;
}; 

And you either instantiate A&lt;Xfoo&gt; or A&lt;Xbar&gt; rather than A&lt;X&gt;.

I suppose you have more than just one type X, then Xfoo and Xbar can be parametrized on the type to be wrapped.

huangapple
  • 本文由 发表于 2023年2月16日 16:40:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/75469670.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定