有没有办法在C ++编译时更改函数原型?

时间:2019-12-29 00:52:31

标签: c++ c++11 c++14 c++17

假设您必须编写应在C ++,C ++ 11,C ++ 17等环境下编译的代码。

例如这样的功能。

bool Ispalindrome(const std::string &str) 
{ 
   // Code 
}

可以在所有C ++实现中进行编译。但是,如果您想使用新旧的C ++ 17 string_view功能,则需要处理类似

#ifdef LEGACYCPP
   bool Ispalindrome(const std::string &str) 
  { 
     // Code 
  }
#elseif CPP17
  bool Ispalindrome(std::string_view str) 
  { 
     // OMG Repeated Code 
  }
#endif

使用条件编译是正确的,但是必须重复代码。

在编译时是否可以选择函数原型?还是其他避免双重编码的方式? (在可以应用的情况下)

谢谢

3 个答案:

答案 0 :(得分:3)

如果可以确保在每种情况下函数的代码段都等同于 ,则可以对参数列表使用宏定义:

#ifdef ISCPP17
#define PALIN_PARAMS std::string_view str
#else
#define PALIN_PARAMS const std::string& str
#endif
bool Ispalindrome(PALIN_PARAMS) 
{ 
    // Code 
}
#undef PALIN_PARAMS

关于此主题,当然有很多变体:您可以在宏定义中省略“ str”部分,并在签名中使用(PALIN_PARAMS str)。但是,使用“按原样”还将允许使用不同类型的多个参数。

但是我不确定这种事情是否会通过C++清教徒的宗教裁判所

另一种(可能更健壮)的方法是将条件编译块与using(或typedef)语句一起使用以定义参数类型:

#ifdef ISCPP17
using cnststrg = std::string_view; // Or typedef std::string_view cnststrg;
#else
using cnststrg = const std::string&;
#endif
bool Ispalindrome(cnststrg str)
{
    // Code 
    return true;
}

答案 1 :(得分:3)

在头文件中,您需要执行类似的操作

#if __cplusplus >= 201703L
   #include <string_view>
   bool Ispalindrome(std::string_view str);
#else
   #include <string>
   bool Ispalindrome(const std::string &str);
#endif

在您的定义中,您需要先添加标题,然后执行

#if __cplusplus >= 201703L
    bool Ispalindrome(std::string_view str) 
#else
    bool Ispalindrome(const std::string &str)
#endif
{ 
 // OMG no repeated code 
}

__cplusplus在标准中指定,并且在每个编译单元中都已预定义。 201703L表示C ++ 17编译器,值越大,表示最新的标准。

这假设一个实现(编译器和库)正确声明符合各自的C ++标准。

答案 2 :(得分:2)

然后提供完全重复的代码,请执行以下较小更改:

#ifdef CPP17
  bool Ispalindrome(std::string_view str)
#else // all versions of LEGACYCPP
  bool Ispalindrome(const std::string &str)
#endif
  { 
     // Same Code 
  }

如果功能的一小部分是版本独有的,则也可以在上面应用相同的技巧。