Com*_* 10 6 c++ macros static templates
有没有办法,大概是使用模板,宏或两者的组合,我可以通常将一个函数应用于不同类的对象,但如果它们没有特定的功能,它们会以不同的方式响应吗?
我特别想要应用一个函数,如果对象具有该函数,将输出对象的大小(即集合中的对象数),但如果对象没有,则将输出一个简单的替换(例如"N/A") "T.即
NO_OF_ELEMENTS( mySTLMap ) -----> [ calls mySTLMap.size() to give ] ------> 10
NO_OF_ELEMENTS( myNoSizeObj ) --> [ applies compile time logic to give ] -> "N/A"
Run Code Online (Sandbox Code Playgroud)
我希望这可能类似于静态断言,尽管我显然想要编译不同的代码路径而不是在构建阶段失败.
Gri*_*zly 12
根据我的理解,您希望进行通用测试,以查看某个类是否具有某个成员函数.这可以使用SFINAE在C++中完成.在C++ 11中,它非常简单,因为您可以使用decltype:
template <typename T>
struct has_size {
private:
template <typename U>
static decltype(std::declval<U>().size(), void(), std::true_type()) test(int);
template <typename>
static std::false_type test(...);
public:
typedef decltype(test<T>(0)) type;
enum { value = type::value };
};
Run Code Online (Sandbox Code Playgroud)
如果你使用C++ 03,由于缺少它会更难decltype,所以你必须滥用sizeof:
template <typename T>
struct has_size {
private:
struct yes { int x; };
struct no {yes x[4]; };
template <typename U>
static typename boost::enable_if_c<sizeof(static_cast<U*>(0)->size(), void(), int()) == sizeof(int), yes>::type test(int);
template <typename>
static no test(...);
public:
enum { value = sizeof(test<T>(0)) == sizeof(yes) };
};
Run Code Online (Sandbox Code Playgroud)
当然这会使用Boost.Enable_If,这可能是一个不需要的(和不必要的)依赖.然而写enable_if自己很简单:
template<bool Cond, typename T> enable_if;
template<typename T> enable_if<true, T> { typedef T type; };
Run Code Online (Sandbox Code Playgroud)
在这两种情况下,方法签名test<U>(int)只有可见,如果U有size方法,因为否则评估decltype或sizeof(取决于您使用的版本)将失败,这将从考虑中删除该方法(由于SFINAE.冗长的表达式std::declval<U>().size(), void(), std::true_type()是一个C++逗号操作符,其将返回从逗号分隔的列表的最后一个表达式,所以这可以确保类型被称为的滥用std::true_type为C++ 11变体(和sizeof求值int的C++ 03变体),该void()中中间只是为了确保逗号运算符没有奇怪的重载干扰评估.
当然,如果T有一个size可以不带参数调用的方法,这将返回true ,但不保证返回值.我假设您可能只想检测那些不返回void的方法.只需稍微修改一下test(int)方法即可轻松完成:
// C++11
template <typename U>
static typename std::enable_if<!is_void<decltype(std::declval<U>().size())>::value, std::true_type>::type test(int);
//C++03
template <typename U>
static typename std::enable_if<boost::enable_if_c<sizeof(static_cast<U*>(0)->size()) != sizeof(void()), yes>::type test(int);
Run Code Online (Sandbox Code Playgroud)
关于constexpr某些人以前的能力的讨论.我觉得是时候使用了它:)
使用constexpr和设计特征很容易decltype:
template <typename T>
constexpr decltype(std::declval<T>().size(), true) has_size(int) { return true; }
template <typename T>
constexpr bool has_size(...) { return false; }
Run Code Online (Sandbox Code Playgroud)
事实上,这种特质很容易失去其大部分价值:
#include <iostream>
#include <vector>
template <typename T>
auto print_size(T const& t) -> decltype(t.size(), void()) {
std::cout << t.size() << "\n";
}
void print_size(...) { std::cout << "N/A\n"; }
int main() {
print_size(std::vector<int>{1, 2, 3});
print_size(1);
}
Run Code Online (Sandbox Code Playgroud)
在行动:
3
N/A
Run Code Online (Sandbox Code Playgroud)