如果在 c++ 之前未定义,则定义函数/方法
Define function / method if not defined before c++
我还没有使用C++11,所以我自己写了函数to_string(whatever)
。只有在它们不存在时才应该编译它们。如果我切换到 C++11,它们应该被跳过。我有这样的东西:
#ifndef to_string
string to_string(int a){
string ret;
stringstream b;
b << a;
b >> ret;
return ret;
}
string to_string(double a){
string ret;
stringstream b;
b << a;
b >> ret;
return ret;
}
#endif
这显然不起作用。这样的事情有可能吗?如果有,怎么办?
你无法测试它们是否被这样定义,但你可以检查语言版本:
#if __cplusplus < 201103L
(有一组有用的预定义编译器宏 here。)
Boost.Config has some macros 检查 C++11 功能是否 supported/used.
这是namespace
存在的主要目的之一。
我的建议是将您的个人功能包含在适当的命名空间中,例如:
namespace myns {
std::string to_string(...) {
// ...
}
// etc...
}
这是避免未来冲突问题的基础。
之后,当您要使用该函数时,您可以通过 MACRO
替换来简化 select 正确的函数。
类似于:
#if (__cplusplus >= 201103L)
#define my_tostring(X) std::to_string(X)
#else
#define my_tostring(X) myns::to_string(X)
#endif
注意__cplusplus
是一个pre-defined macro,包含标准版本的编译信息。
编辑:
少了一些 "violent",它将 select 根据标准版本为该特定功能提供适当的命名空间:
#if (__cplusplus >= 201103L)
using std::to_string;
#else
using myns::to_string;
#endif
// ... somewhere
to_string(/*...*/); // it should use the proper namespace
您可以将函数放在宏中,如下所示:
#ifndef to_string
#define to_string
//....
#endif
然后,在另一个文件中,这样写:
#if __cplusplus >= 201103L
#undef to_string
#else
#define to_string
#endif
您可以使用 SFINAE,记住非模板重载优于模板重载。这在 pre-c++11 和 c++11 中编译:
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
namespace my {
template <bool V, class T>
struct enable_if {
};
template <class T>
struct enable_if<true, T> {
typedef T type;
};
template <class T1, class T2>
struct is_same {
static const bool value = false;
};
template <class T>
struct is_same<T, T> {
static const bool value = true;
};
}
template <class T>
typename my::enable_if<my::is_same<T, int>::value
|| my::is_same<T, double>::value, string>::type
to_string(T const& a) {
string ret;
stringstream b;
b << a;
b >> ret;
return ret;
}
int main() {
cout << to_string(2) << endl;
cout << to_string(3.4) << endl;
}
我还没有使用C++11,所以我自己写了函数to_string(whatever)
。只有在它们不存在时才应该编译它们。如果我切换到 C++11,它们应该被跳过。我有这样的东西:
#ifndef to_string
string to_string(int a){
string ret;
stringstream b;
b << a;
b >> ret;
return ret;
}
string to_string(double a){
string ret;
stringstream b;
b << a;
b >> ret;
return ret;
}
#endif
这显然不起作用。这样的事情有可能吗?如果有,怎么办?
你无法测试它们是否被这样定义,但你可以检查语言版本:
#if __cplusplus < 201103L
(有一组有用的预定义编译器宏 here。)
Boost.Config has some macros 检查 C++11 功能是否 supported/used.
这是namespace
存在的主要目的之一。
我的建议是将您的个人功能包含在适当的命名空间中,例如:
namespace myns {
std::string to_string(...) {
// ...
}
// etc...
}
这是避免未来冲突问题的基础。
之后,当您要使用该函数时,您可以通过 MACRO
替换来简化 select 正确的函数。
类似于:
#if (__cplusplus >= 201103L)
#define my_tostring(X) std::to_string(X)
#else
#define my_tostring(X) myns::to_string(X)
#endif
注意__cplusplus
是一个pre-defined macro,包含标准版本的编译信息。
编辑:
少了一些 "violent",它将 select 根据标准版本为该特定功能提供适当的命名空间:
#if (__cplusplus >= 201103L)
using std::to_string;
#else
using myns::to_string;
#endif
// ... somewhere
to_string(/*...*/); // it should use the proper namespace
您可以将函数放在宏中,如下所示:
#ifndef to_string
#define to_string
//....
#endif
然后,在另一个文件中,这样写:
#if __cplusplus >= 201103L
#undef to_string
#else
#define to_string
#endif
您可以使用 SFINAE,记住非模板重载优于模板重载。这在 pre-c++11 和 c++11 中编译:
#include <sstream>
#include <string>
#include <iostream>
using namespace std;
namespace my {
template <bool V, class T>
struct enable_if {
};
template <class T>
struct enable_if<true, T> {
typedef T type;
};
template <class T1, class T2>
struct is_same {
static const bool value = false;
};
template <class T>
struct is_same<T, T> {
static const bool value = true;
};
}
template <class T>
typename my::enable_if<my::is_same<T, int>::value
|| my::is_same<T, double>::value, string>::type
to_string(T const& a) {
string ret;
stringstream b;
b << a;
b >> ret;
return ret;
}
int main() {
cout << to_string(2) << endl;
cout << to_string(3.4) << endl;
}