2

次のように定義された構造体があります。

struct A : public B, public C
{
    A(const B& b) : B(b), C()
    {}

    template<typename... Args>
    A(Args&&... args) : B(), C(std::forward<Args>(args)...)
    {}
};

int main()
{
   B b;

   A sample1(b);
   A sample2(3); // For example, B has a B(int) constructor.
}

そして、これはうまくいきA(b)ませBB(A&).

moveさらに、 B のコンストラクターを追加したい:

struct A : public B, public C
{
    A(const B& b) : B(b), C()
    {}

    A(B&& b) : B(std::move(b)), C()
    {}

    template<typename... Args>
    A(Args&&... args) : B(), C(std::forward<Args>(args)...)
    {}
};

最後のステップは、最初の 2 つのコンストラクターを融合することです。

struct A : public B, public C
{
   template<typename fw_B>
   A(fw_B&& b) : B(std::forward<fw_B>(b)), C()
   {}

   template<typename... Args>
   A(Args&&... args) : B(), C(std::forward<Args>(args)...)
   {}
 };

質問: 最初のバージョンが衝突を引き起こした場合、最後のバージョン (私の最終的な目的) も機能しないことは明らかです。どうすればこの目標を達成できますか?

4

1 に答える 1

2

可能な解決策は、引数のタイプが次のように変換可能な場合にのみ、最初のコンストラクターを含めるために使用std::enable_ifされます。std::is_convertiblebB

template <
  class fw_B,
  class = typename std::enable_if<std::is_convertible<fw_B, B>::value, T>::type>
A(fw_B&& b)

例えば:

#include <iostream>
#include <type_traits>

struct B
{
    B() {}
    B(int) {}
};

struct C {};

struct A : B, C
{
    template <
      class T,
      class = typename std::enable_if<std::is_convertible<T, B>::value, T>::type> 
    A(T&& t) { std::cout << "A(T&&)\n"; }

    template <class... TArgs>
    A(TArgs&&... targs) { std::cout << "A(TArgs&&)\n"; }
};

int main()
{
    B b;

    A a1(b);
    A a2(4);
    A a3("hello");

    return 0;
}

出力:

で&&)
で&&)
A(TArgs &&)

http://ideone.com/xJEjicのデモを参照してください。

于 2013-02-04T11:16:15.243 に答える