簡體   English   中英

調用模板化類型的不同構造函數簽名

[英]Calling different constructor signatures of templated Types

我手頭有大量的模板代碼,其中應該用作用戶代碼模板參數的類具有不同的構造函數簽名。 我的問題是,我還沒有找到在用戶代碼中調用模板化類的構造函數的好方法。 一個最小的工作示例可能如下所示:

#include <string>
#include <iostream>
#include <memory>

class ShortConstructorInLibrary {
    std::string myName;
    static const int tag = 1;
public:
    ShortConstructorInLibrary(std::string name) :
            myName(name) {
    }
};

class LongConstructorInLibrary {
private:

    int a;
    double b;
public:
    static const int tag = 2;
    LongConstructorInLibrary(int arg1, double arg2) :
            a(arg1), b(arg2) {
    }
};
//above is library code

template<typename T>
class MyClass {
    std::shared_ptr<T> member_p;
    //i want to call right constructor for both cases:
public:
    MyClass() {

        //how do i call the different constructors properly?!
        member_p = std::shared_ptr<T>(new T("test"));
    }

};

int main() {
    MyClass<ShortConstructorInLibrary> obj;     //works
    //MyClass<LongConstructorInLibrary> obj2;   // wrong constructor signature
}

在這里,我在一個庫中有兩個類,一個類具有較長且無關的構造函數簽名,一個類具有較短的類。 我希望能夠將它們都用作模板參數。 在我的userClass中,我必須以某種方式定義要傳遞給構造函數的參數,具體取決於傳遞的類型。

我不能使用簡單的if(),因為編譯器將同時檢查兩個簽名,而一個簽名將是錯誤的。 我不能將c ++ 17用作“ if constexpr(){}”。

我可以將模板參數“ ShortConstructorInLibrary”傳遞給我的類,並完美地調用它的構造函數,但是當我使用另一個類時,它當然會因錯誤的構造函數簽名而失敗。 到目前為止,我使用了一個丑陋的把戲,以至於我實現了兩個輔助方法,在該方法中我傳遞了一個指針,然后讓這兩個方法實現了構造函數調用,但這對我來說似乎很丑陋。 我還擺弄了std :: enable_if <>,但走得並不遠。 @Mohit提議使用部分模板專門化,但是在現實世界的代碼中,Short ConstructorInLibrary類本身是使用兩個... templateed模板參數進行模板化的。 給您一個想法:

‘class CFEM_LOP<Dune::PDELab::QkLocalFiniteElementMap<Dune::GridView<Dune::DefaultLeafGridViewTraits<const Dune::YaspGrid<2> > >, double, double, 1ul>, EngwHillenKnapp2014<MedicalDataManager<double, Dune::YaspGrid<2> >, Dune::YaspGrid<2> >, CFEM_L2OP<Dune::PDELab::QkLocalFiniteElementMap<Dune::GridView<Dune::DefaultLeafGridViewTraits<const Dune::YaspGrid<2> > >, double, double, 1ul> >, Dune::YaspGrid<2> >’

我跌倒了,試圖專門化我的用戶代碼將是一團糟。

實施可能變化的簽名的構造函數調用的正確方法是什么?

任何提示將不勝感激!

(Ubuntu 16.04,GCC)

嘗試使用部分專業化方法來實現這一點,我使用std::make_shared創建std::shared_ptr

class ShortConstructorInLibrary
{
    std::string myName;
    static const int tag = 1;
public:
    ShortConstructorInLibrary(std::string name) :
        myName(name)
    {
    }
};

class LongConstructorInLibrary
{
private:

    int a;
    double b;
public:
    static const int tag = 2;
    LongConstructorInLibrary(int arg1, double arg2) :
        a(arg1), b(arg2)
    {
    }
};
//above is library code

template<typename T>
class MyClass
{
    std::shared_ptr<T> member_p;
    //i want to call right constructor for both cases:
public:
    MyClass()
    {

        //how do i call the different constructors properly?!
        member_p = std::make_shared<T>("test");
    }

};

template<>
MyClass<LongConstructorInLibrary>::MyClass()
{
    member_p = std::make_shared<LongConstructorInLibrary>(0, 0.0); // pass you values.
}

int main()
{
    MyClass<LongConstructorInLibrary> obj;     //works
                                                //MyClass<LongConstructorInLibrary> obj2;   // wrong constructor signature
}

MyClass的構造函數應該創建一個T類型的對象。 假定作為模板參數傳遞的每個T具有不同的構造函數簽名,因此您需要將構造T所需的參數傳遞給類MyClass並轉發這些參數。 這是可能的,因為c ++ 11具有可變參數模板,即

template <class T>
struct MyClass
{
  std::shared_ptr<T> member_p;

  template <class... Args>
  MyClass(Args&&... args)
    : member_p(std::make_shared<T>(std::forward<Args>(args)...))
  {}
};

int main() {
  MyClass<ShortConstructorInLibrary> obj1("test");
  MyClass<LongConstructorInLibrary> obj2(1, 2.0);
}

您只需要謹慎使用可變的通用構造函數參數,因為這也涵蓋了復制/移動構造函數。 為了不使用您的書面構造函數停用這些功能,您必須添加一點enable_if代碼。 由於使用Dune ,因此您可以簡單地應用一個通用模式:

template <class... Args, Dune::disableCopyMove<MyClass, Args...> = 0>
MyClass(Args&&... args)
  : member_p(std::make_shared<T>(std::forward<Args>(args)...))
{}

disableCopyMoveenable_if的包裝,如果將MyClass const&MyClass&&傳遞給構造函數,則會導致替換失敗,從而使自定義構造函數不會隱藏copy和move構造函數。 = 0是必需的,因為此enable_if包裝器定義的類型是int ,而= 0是此非類型模板參數的默認值,因此您無需自己指定它。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM