2015-06-11 53 views
0

假設我有幾種類型綁定到一個變體中。 在另一邊,我有一些以前的類型可以從推測的枚舉,這樣我就可以有一個運行時的僞工廠:構造enum類型並轉發不同數量的參數

#include <boost/variant.hpp> 

enum class Type { W, X, Y, Z }; 

struct A {}; 

struct B 
{ 
    B(int) {} 
}; 

struct C 
{ 
    C(int, int) {} 
}; 

using variant_t = boost::variant<A, B, C>; 

template<typename... Args> 
variant_t MakeVariantOverEnum(Type type, Args&&... args) 
{ 
    switch (type) 
    { 
     case Type::X: return B(std::forward<Args>(args)...); break; 
     case Type::Z: return C(std::forward<Args>(args)...); break;    
     default:  return A(std::forward<Args>(args)...); break; 
    } 
} 

// meant to be fully runtime 
const Type GetTypeFromIO() { return Type::Z; } 
const int GetFirstArgFromIO() { return 0; } 
const int GetSecondArgFromIO() { return 0; } 

int main() 
{ 
    const Type type = GetTypeFromIO(); 
    const int firstArg = GetFirstArgFromIO(); 
    const int secondArg = GetSecondArgFromIO();  

    variant_t newVariant; 

    if (firstArg != 0 && secondArg != 0) newVariant = MakeVariantOverEnum(type, firstArg, secondArg); 
    else if (firstArg != 0)    newVariant = MakeVariantOverEnum(type, firstArg); 
    else         newVariant = MakeVariantOverEnum(type); 
} 

兩件事情打擾我在此代碼:

* *如何通過傳遞所有參數,然後丟棄那些'無效'的情況(我的示例中爲== 0),只有1次調用MakeVariantOverEnum?我可以在MakeVariantOverEnum中使用一些SFINAE機制嗎?

**它不會編譯,因爲編譯器嘗試所有構造函數的所有參數匹配:

main.cpp: In instantiation of 'variant_t MakeVariantOverEnum(Type, Args&& ...) [with Args = {const int&, const int&}; variant_t = boost::variant<A, B, C>]': 
main.cpp:44:100: required from here 
main.cpp:24:59: error: no matching function for call to 'B::B(const int&, const int&)' 
     case Type::X: return B(std::forward<Args>(args)...); break; 
                 ^
main.cpp:24:59: note: candidates are: 
main.cpp:9:2: note: B::B(int) 
    B(int) {} 
^
main.cpp:9:2: note: candidate expects 1 argument, 2 provided 
main.cpp:7:8: note: constexpr B::B(const B&) 
struct B 
     ^
main.cpp:7:8: note: candidate expects 1 argument, 2 provided 
main.cpp:7:8: note: constexpr B::B(B&&) 
main.cpp:7:8: note: candidate expects 1 argument, 2 provided 

等了其他類型...

所以我的問題是:我現在怎麼才能使它工作?

謝謝!

PS:代碼是住在這裏=>http://coliru.stacked-crooked.com/a/4bc1e326be27b3dd

回答

0

最簡單的爲您的問題的方法:

enum class Type { W, X, Y, Z }; 

struct A {}; 

struct B 
{ 
    B(int) {} 
}; 

struct C 
{ 
    C(int, int) {} 
}; 

using variant_t = boost::variant<A, B, C>; 

variant_t MakeVariantOverEnum(Type type, int param1, int param2) 
{ 
    switch (type) 
    { 
     case Type::X: return B(param1); 
     case Type::Z: return C(param1, param2);    
     default:  return A(); 
    } 
} 

// meant to be fully runtime 
const Type GetTypeFromIO() { return Type::Z; } 
const int GetFirstArgFromIO() { return 0; } 
const int GetSecondArgFromIO() { return 0; } 

int main() 
{ 
    const Type type = GetTypeFromIO(); 
    const int firstArg = GetFirstArgFromIO(); 
    const int secondArg = GetSecondArgFromIO();  

    variant_t newVariant = MakeVariantOverEnum(type, firstArg, secondArg); 
} 

的可變參數模板只是使事情變得更加複雜,不會幫助你以任何方式。

如果你所有的結構都使用相同的參數(至少:如果使用參數,相同的類型在任何地方使用),這將工作。但是,如果針對不同對象具有不同的參數類型,則需要考慮在主功能本身中執行開關是否不容易(然後獲取正確的參數):

假設以下擴展:

struct D 
{ 
    D(float) {} 
} 

所以,現在你突然有

或者您指定的第三個參數float param3只有使用這樣的情況下你const int firstArg將是一個浮...(不會對B和C但是工作)參數創建類型時。 (但那麼參數1和參數2呢?)

注意:它仍然可以使用一些工廠模式,但這會更復雜一點(每個對象都需要自己的工廠,這將獲得正確的參數和然後創建正確的結構...)

相關問題