是否可以编写一个模板来改变行为,具体取决于是否在类上定义了某个成员函数?
这是我想写的一个简单例子:
template<class T>
std::string optionalToString(T* obj)
{
if (FUNCTION_EXISTS(T->toString))
return obj->toString();
else
return "toString not defined";
}
Run Code Online (Sandbox Code Playgroud)
所以,如果class T已经toString()确定的话,就使用它; 否则,它没有.我不知道怎么做的神奇部分是"FUNCTION_EXISTS"部分.
我编写了以下模板函数,它检查仲裁容器是否包含特定元素:
template<template<class, class...> class container_t, class item_t, class... rest_t>
bool contains(const container_t<item_t, rest_t...> &_container, const item_t &_item) {
for(const item_t &otherItem : _container) {
if(otherItem == _item) { return true; }
}
return false;
}
Run Code Online (Sandbox Code Playgroud)
这适用于大多数容器.然而,对于所有类型的集合(和地图),它是次优的,因为我们可以使用:
template<template<class, class...> class set_t, class item_t, class... rest_t>
bool contains(const set_t<item_t, rest_t...> &_set, const item_t &_item) {
return _set.count(_item) > 0;
}
Run Code Online (Sandbox Code Playgroud)
显然,由于含糊不清,我们不能同时使用这两个模板.现在我正在寻找一种方法,用于std::enable_if启用第一个模板,如果container_t不提供count成员函数,第二个模板,如果它没有.但是我无法弄清楚如何检查特定成员函数(使用C++ 11).
在尝试创建特征以检查类字段是否公开可用时,我创建了一个代码:
#include <type_traits>
#include <utility>
template <class T, class = void>
struct does_not_have_foo: std::true_type {};
template <class T>
struct does_not_have_foo<T, decltype(std::declval<T>().foo, void())>: std::false_type {};
class Foo {
int foo;
};
int main() {
static_assert(does_not_have_foo<Foo>::value);
}
Run Code Online (Sandbox Code Playgroud)
但它似乎未能在[gcc]中编译([clang]似乎在这里更宽松)并出现错误:
prog.cc:8:56: error: 'int Foo::foo' is private within this context
Run Code Online (Sandbox Code Playgroud)
我为我的一些旧代码挖出了类似的东西,归结为以下内容:
template <class T>
auto does_not_have_foo(T t) -> decltype(t.foo, std::false_type()) {
return {};
}
std::true_type does_not_have_foo(...) { return {}; }
class Foo {
int foo;
};
int main() {
static_assert(decltype(does_not_have_foo(Foo{}))::value);
} …Run Code Online (Sandbox Code Playgroud) 当我添加 -Wshadow 标志时,编译器(gcc 12.1.0)会为以下代码生成以下警告:
prog.cc: In member function 'void Derived::myfunc()':
prog.cc:16:13: warning: declaration of 'i' shadows a member of 'Derived' [-Wshadow]
16 | int i = 3;
| ^
prog.cc:8:9: note: shadowed declaration is here
8 | int i{2};
|
Run Code Online (Sandbox Code Playgroud)
class Base
{
private:
int i{2};
};
class Derived : public Base
{
public:
void myfunc(void)
{
int i = 3;
std::cout << i << "\n";
}
};
Run Code Online (Sandbox Code Playgroud)
我的想法是:因为我们不能在 myfunc 中仅使用“i”变量(因为它是编译时错误),所以没有必要发出这样的警告。
您知道为什么编译器在这种情况下会发出警告吗?