有人知道如何检查任意方法是否为const?
像:
static_assert(is_const<vector<int>::size>::value, "size is not const");
static_assert(!is_const<vector<int>::push_back>::value, "push_back is const");
好问题T.C :)我发现方法的特殊重载,我想只设置一个修改过的标志,如果我找到的方法是非const。
这是我的模板和色情:
#define FRET_DECL_TYPE(Function) \
template<typename T_, typename ... Args_> \
struct f_ret##Function { typedef decltype(std::declval<T_&>().Function(std::declval<Args_&&>()...)) type; };
#define RPROP_PROXY_METHOD(Function) \
FRET_DECL_TYPE(Function) \
template<typename ... Args> \
typename f_ret##Function<T, Args...>::type \
Function(Args&& ... args) const { return this->GetReference().Function(static_cast<Args&&>(args)...); }; \
template<typename ... Args> \
typename f_ret##Function<T, Args...>::type \
Function(Args&& ... args) { this->SetModified(true); return this->GetReference().Function(static_cast<Args&&>(args)...); }; \
答案 0 :(得分:3)
可以使用“Walter Brown's void_t
trick”完成,但如果你需要很多成员,它会很快变得有点冗长。您可以考虑使用宏来避免一次又一次地重复每个成员的模板定义。
#include <iomanip>
#include <iostream>
#include <type_traits>
#include <vector>
template<typename>
struct void_t
{
using type = void;
};
template<class C, typename = void>
struct has_const_size : std::false_type {};
template<class C>
struct has_const_size<C, typename void_t<decltype(std::declval<const C>().size())>::type> : std::true_type {};
template<class C, typename = void>
struct has_const_clear : std::false_type {};
template<class C>
struct has_const_clear<C, typename void_t<decltype(std::declval<const C>().clear())>::type> : std::true_type {};
int
main()
{
std::cout << "std::vector<int>::size() " << std::boolalpha << has_const_size<std::vector<int>>::value << std::endl;
std::cout << "std::vector<int>::clear() " << std::boolalpha << has_const_clear<std::vector<int>>::value << std::endl;
}
输出:
std::vector<int>::size() true
std::vector<int>::clear() false
答案 1 :(得分:2)
我接受它,愿意接受建议。
编辑1:缺少参考资格。这是一个快速而肮脏的解决方案,只是为了拥有真正有用的东西 编辑2:在等式中添加了varargs。实施变得越来越难看,但我觉得调用风格很好。
#include <iostream>
template <class... Ttypes>
struct params {};
#define isConstDuet(q) \
template <class T, class Tret, class... Targs> \
constexpr bool isConst(Tret (T::*)(Targs...) q, \
params<Targs...> = {}) { \
return false; \
} \
\
template <class T, class Tret, class... Targs> \
constexpr bool isConst(Tret (T::*)(Targs...) const q, \
params<Targs...> = {}) { \
return true; \
} \
template <class T, class Tret, class... Targs> \
constexpr bool isConst(Tret (T::*)(Targs..., ...) q, \
params<Targs...> = {}) { \
return false; \
} \
\
template <class T, class Tret, class... Targs> \
constexpr bool isConst(Tret (T::*)(Targs..., ...) const q,\
params<Targs...> = {}) { \
return true; \
}
isConstDuet()
isConstDuet(&)
isConstDuet(&&)
isConstDuet(volatile)
isConstDuet(volatile&)
isConstDuet(volatile&&)
#undef isConstDuet
struct S {
void a() {}
void b() const {}
void c(int) {}
void c(float) const {}
void d() & {}
void e() && {}
void f() volatile & {}
void g() volatile && {}
void d2() const & {}
void e2() const && {}
void f2() const volatile & {}
void g2() const volatile && {}
void h(...) {}
void h2(...) const {}
};
int main() {
std::cout << std::boolalpha;
std::cout << isConst(&S::a) << '/' << isConst(&S::b) << '\n';
std::cout << isConst(&S::c, params<int>{})
<< '/' << isConst(&S::c, params<float>{}) << '\n';
std::cout << isConst(&S::d) << '/' << isConst(&S::d2) << '\n';
std::cout << isConst(&S::e) << '/' << isConst(&S::e2) << '\n';
std::cout << isConst(&S::f) << '/' << isConst(&S::f2) << '\n';
std::cout << isConst(&S::g) << '/' << isConst(&S::g2) << '\n';
std::cout << isConst(&S::h) << '/' << isConst(&S::h2) << '\n';
return 0;
}
输出:
false/true
false/true
false/true
false/true
false/true
false/true
false/true
答案 2 :(得分:1)
另一种可能的解决方案:
#include <vector>
struct Q {
void push_back(int i) const {}
};
template<typename A, typename B>
struct First {
typedef A type;
};
template<typename T>
constexpr typename
First<
bool,
decltype(std::declval<T const>().push_back(4))
>::type
test(int) {
return 0;
}
template<typename T>
constexpr bool test(double) {
return 1;
}
static_assert(test<Q>(0), "bad");
如果方法是const,则两个函数都是可能的,但编译器将选择带有int参数的函数以避免转换。如果它不是const,则只有第二个是可能的。