2017-08-10 84 views
-3

我想编写一个C++函数,它根据第一个参数调整第二个参数的类型。所以我有这样的事情:在C++中更改参数类型的最佳做法

enum FtnType { FTN_A, FTN_B, FTN_C }; 

void bar(FtnType foo, const int arg = 0) 
{ 
    switch(foo) 
    { 
     case 0: 
      { 
       void ftnA(arg); 
       break; 
      } 
     case 1: 
      { 
       void ftnB(); 
       break; 
      } 
     case 2: 
      { 
       void ftnC(arg); 
       break; 
      } 
    } 
} 

现在对于case 0我想ARG是一个整数,case 1我不希望使用任何参数和case 3我想ARG类型为浮动。我知道我可以在一个案例中投出类型,但这似乎是一个糟糕的编程习惯。什么应该是解决这个问题的最好方法?

+0

石膏。 'static_cast',如果可以的话。 –

+0

调用'bar()'的人怎么知道它会决定它想要的类型? – Galik

+0

我想你会需要一个模板或超负荷,如果你想'arg'是'int'或'float'当你打电话给''' – bbaldino

回答

0

在我看来,根据第一个参数,你想采取不同类型的第二个参数。 C++是一种强类型语言,这意味着您需要在编译时知道第一个参数的值。这将我们带入模板领域(我高兴)。另一个问题是,如果您希望修改它,则需要通过引用传递第二个参数。

enum class FtnType { ftn_a, ftn_b, ftn_c }; 

template <FtnType type> struct Modify; 

template <> struct Modify<FtnType::ftn_a> 
{ 
    static auto modify(int& a) 
    { 
     ftnA(a); 
    } 
} 

template <> struct Modify<FtnType::ftn_b> 
{ 
    static auto modify() 
    { 
     ftnB(); 
    } 
} 

template <> struct Modify<FtnType::ftn_c> 
{ 
    static auto modify(float& a) 
    { 
     ftnC(a); 
    } 
} 

与用法:

int main() 
{ 
    int a = 24; 
    float f = 42.f; 

    Modify<FtnType::ftn_a>::modify(a); 
    Modify<FtnType::ftn_b>::modify(); 
    Modify<FtnType::ftn_c>::modify(f); 
} 

该作品以具有FtnType模板一个结构和各专门为FtnType有不同的签名静态modify功能。

0

不知道我是否理解你的问题是正确的,但会超载这样的工作?

void bar (int arg) 
{ 
    ftnA(arg); 
} 

void bar (float arg) 
{ 
    ftnC(arg); 
} 

void bar() 
{ 
    ftnB(); 
} 
0

你不需要所有这些功能和enum。只需使用重载函数:

void ftn(int arg) 
{ 
    std::cout << "I've got an int!" << std::endl; 
    // Do stuff which is in ftnA 
} 

void ftn(float arg) 
{ 
    std::cout << "I've got an float!" << std::endl; 
    // Do stuff which is in ftnC 
} 

void ftn() 
{ 
    std::cout << "I've got nothing! :(" << std::endl; 
    // Do stuff which is in ftnB 
} 

和简单的调用

ftn(5); // Will print 'I've got an integer!' 
ftn(5.0f); // Will print 'I've got an float!' 
ftn();  // Will print 'I've got nothing! :(' 
0
enum class FtnType {FTN_A, FTN_B, FTN_C}; 

void bar(FtnType foo, const int arg = 0) { 
    [&] { 
     switch(foo) { 
      case FtnType::FTN_A: 
       return ftnA(arg); 
      case FtnType::FTN_B: 
       return ftnB(); 
      case FtnType::FTN_C: 
       return ftnC(static_cast<double>(arg)); 
     } 
    }(); 
} 

Live example

1

您正在尝试混合编译时一个有趣的组合和运行时的逻辑。虽然您可能通过使用模板来实现某些功能,但通过将参数1指定为编译时已知值,我并不完全确定这是可取的。

你要求一个最佳实践,老实说,我认为最好的做法是退后一步,重新考虑你的设计。为什么你需要你的功能根据参数1工作如此不同?

如果您要更改参数2的值(例如在经典的printf中使用的variadic arguments类似的函数),那么您将有一个在编译时很难检测到的错误源,甚至难以检测运行时间。

你可以使用可变参数模板(虽然我还是建议重新考虑你的设计)考虑一个更编译时间友好的方法:

template <typename F, typename... T> 
void bar(F func, T... params) { 
    func(params...); 
} 

对这种做法的好处,是不小心传递错误的参数类型,或参数个数,会导致编译时错误。这种方法将要求您知道在bar之外执行的功能。

void test1(int a, double b, char c) { 
    std::cout << "test1(" << a << ", " << b << ", " << c << ")\n"; 
} 

void test2() { 
    std::cout << "test2()\n"; 
} 

int main() { 
    bar(test1, 1, 2.1, 'c'); 
    bar(test2); 
    return 0; 
} 

这个测试代码可以在这里找到运行:http://ideone.com/vU30qn和输出:

test1(1, 2.1, c) 
test2()