我很生气,如果容器包含一个元素,STL容器没有contains()返回true的方法,false否则.所以,我坐下来写下这个:
template <typename C, typename E>
inline bool contains(const C& container, const E& element) {
return container.find(element) != container.end();
}
Run Code Online (Sandbox Code Playgroud)
它适用于集合和地图,但不适用于矢量.或列表.我该怎么办?我应该写一个额外的
template <typename T>
inline bool contains(const vector<T>& container, const T& element) {
std::find(vector.begin(), vector.end(), item) != vector.end()
}
Run Code Online (Sandbox Code Playgroud)
其他容器的更具体的代码?我是否应该继续使用迭代器的次优使用来逐元素地检查?我真的不愿意这样做......也许我没有注意到一些相关的STL功能?
以此代码为例:
#include <type_traits>
#include <iostream>
struct Foo
{
Foo() = default;
Foo(Foo&&) = delete;
Foo(const Foo&) noexcept
{
std::cout << "copy!" << std::endl;
};
};
struct Bar : Foo {};
static_assert(!std::is_move_constructible_v<Foo>, "Foo shouldn't be move constructible");
// This would error if uncommented
//static_assert(!std::is_move_constructible_v<Bar>, "Bar shouldn't be move constructible");
int main()
{
Bar bar {};
Bar barTwo { std::move(bar) };
// prints "copy!"
}
Run Code Online (Sandbox Code Playgroud)
因为Bar是从Foo派生的,所以它没有移动构造函数.它仍然可以通过使用复制构造函数来构造.我了解了为什么它从另一个答案中选择了复制构造函数:
如果
y是类型S,则std::move(y)类型S&&的引用与类型兼容S&.因此S x(std::move(y))完全有效并调用复制构造函数S::S(const S&) …
我编写了类似于类的特性,如果给定类型是"可迭代的",可以使用它来测试.这对于数组(for T[N],not for T[])以及具有a begin和end返回看起来像迭代器的方法的类都是如此.我想知道它是否可以比我更简洁/更简单地完成?
特别是impl命名空间中的东西看起来有点迂回/ hacky.这一切对我来说都有点难看.有关使用此示例并且可以使用g ++和clang ++编译的示例,请参阅:https://gist.github.com/panzi/869728c9879dcd4fffa8
template<typename T>
struct is_iterator {
private:
template<typename I> static constexpr auto test(void*)
-> decltype(
*std::declval<const I>(),
std::declval<const I>() == std::declval<const I>(),
std::declval<const I>() != std::declval<const I>(),
++ (*std::declval<I*>()),
(*std::declval<I*>()) ++,
std::true_type()) { return std::true_type(); }
template<typename I> static constexpr std::false_type test(...) { return std::false_type(); }
public:
static constexpr const bool value = std::is_same<decltype(test<T>(0)), std::true_type>::value;
};
namespace impl {
// implementation details …Run Code Online (Sandbox Code Playgroud) 这就是我的意思.我有一个类层次结构:
class A {
virtual int f() = 0;
};
class B : public A {
int f() override {return 5;}
void doSpecificStuff() {}
}
Run Code Online (Sandbox Code Playgroud)
B是一个自给自足的类,可以单独使用.但它也有许多后代:
class C : public B {
int f() override {return 171;}
}
Run Code Online (Sandbox Code Playgroud)
有什么方法可以确保f在子类化时我不会忘记重新实现B?
我试图找到一种方法来简单地检查给定名称的方法是否存在于使用 c++11 特性的 c++ 类中,但没有(!)检查签名。
如果没有签名检查,我无法找到任何东西,所以我尝试从这里使用 Valentin Milea 的解决方案并对其进行修改(见下文),但我对 C++ 的理解不够深入,无法真正掌握那里发生的事情:
#include <type_traits>
template <class C>
class HasApproxEqualMethod
{
template <class T>
static std::true_type testSignature(bool (T::*)(const T&, double) const);
template <class T>
static decltype(testSignature(&T::approx_equal)) test(std::nullptr_t);
template <class T>
static std::false_type test(...);
public:
using type = decltype(test<C>(nullptr));
static const bool value = type::value;
};
class Base {
public:
virtual ~Base();
virtual bool approx_equal(const Base& other, double tolerance) const;
};
class Derived : public Base {
public:
// same interface …Run Code Online (Sandbox Code Playgroud) 为什么我需要在线*上制作checker指针
template <typename C> static yes test( checker<C, &C::helloworld>* );
为了使编译时间扣除正常工作,输出1 0?
当我删除时*,输出是0 0
#include <iostream>
struct Generic {};
struct Hello
{ int helloworld() { return 0; } };
// SFINAE test
template <typename T>
class has_helloworld
{
typedef char yes;
typedef struct {char _[2];} no;
template <typename C, int (C::*)()> struct checker;
template <typename C> static yes test( checker<C, &C::helloworld>* );
template <typename C> static no test(...);
public:
enum { …Run Code Online (Sandbox Code Playgroud) 在Perl中,有一个UNIVERSAL :: can方法可以调用任何类或对象来确定它是否能够执行某些操作:
sub FooBar::foo {}
print "Yup!\n" if FooBar->can('foo'); #prints "Yup!"
Run Code Online (Sandbox Code Playgroud)
假设我在C++中有一个基类指针,它可以是许多不同的派生类中的任何一个,是否有一种简单的方法来完成与此类似的操作?我不想触及其他派生类中的任何内容,我只能更改调用该函数的基类中的区域,以及支持它的派生类.
编辑:等等,现在这是显而易见的(永远不要回答问题),我可以在基数中实现它,返回一个代表UNIMPLEMENTED的数字,然后在调用时检查返回不是这个.我不确定为什么我会以如此复杂的方式思考问题.
我也在想我会从另一个实现的类派生出来foo然后看看这个类的动态转换是否有效.
说我有以下代码:
template <class Derived>
class Base {
public:
virtual void foo_impl() = 0;
void foo() {
static_cast<Derived*>(this)->foo_impl(); //A
(*static_cast<Derived*>(this)).foo_impl(); //B
}
};
class Derived : public Base<Derived> {
private:
void foo_impl() {
bar();
}
};
Run Code Online (Sandbox Code Playgroud)
几个问题:
A行会生成虚函数调用吗?虽然我在互联网上找到的大部分内容都建议以这种方式做事,但对于我来说,我并没有看到编译器如何进行静态调度,因为指向Derived的指针实际上仍然可以指向Derived2类型的对象,其中Derived2:公共派生.
B行是否解决了我之前提到的问题(如果适用)?考虑到现在调用不再是指针而是因此使用*,它似乎会这样.会避免虚函数调用.但是如果编译器将解除引用的强制转换视为引用类型,它仍然可以生成虚函数调用......在这种情况下,解决方法是什么?
将C++ 11 final关键字添加到foo_impl()会改变编译器在(或任何其他相关)情况下的行为方式吗?
假设我有这样的模板:
template<class T>
class A
{
...
};
Run Code Online (Sandbox Code Playgroud)
我希望这个模板只有在代替的类型T有特定接口时才能专用.例如,此类型必须具有以下两种方法:
int send(const char* buffer, size_t size);
int receive(char* buffer, size_t size);
Run Code Online (Sandbox Code Playgroud)
我如何对模板进行此限制?谢谢您的帮助!
UPD:
这个问题是关于SFINAE?不是关于内在或类设计.
我在这里发现了几个问题,这些问题涉及检查给定类型是否存在成员函数、自由函数或运算符。提议的解决方案解决了手头的问题,但每个解决方案都使用不同的方法。我试图找到一种方法来以相同或至少类似的方式处理这些问题中的每一个。
检查类型C是否有成员func有效:
template<typename, typename T>
struct has_member {
static_assert(
std::integral_constant<T, false>::value,
"Second template parameter needs to be of function type.");
};
template<typename C, typename Ret, typename... Args>
struct has_member<C, Ret(Args...)> {
private:
template<typename T, std::enable_if_t<
std::is_same
<
decltype(std::declval<T>().func(std::declval<Args>()...)),
Ret
>::value
> * = nullptr >
static constexpr std::true_type check(T*);
template<typename>
static constexpr std::false_type check(...);
typedef decltype(check<C>(nullptr)) type;
public:
static constexpr bool value = type::value;
};
Run Code Online (Sandbox Code Playgroud)
这取自这个问题的最高投票答案: 检查类是否具有给定签名 的成员函数编译条件刚刚从返回类型移至模板参数。
检查是否operator+存在也可以:
template<typename C, typename …Run Code Online (Sandbox Code Playgroud) 我想定义可只适用于各类模板函数的支持乘法,例如int,long,float,和自定义类型的重载运营商如Martix:
class Matrix {
public:
Matrix operator*(const Matrix& other) const;
}
Run Code Online (Sandbox Code Playgroud)
是否可以通过这种方式限制模板类型?
template <typename T, typename = std::enable_if_t< /* multiplication is defined */ >>
T power (T base, unsigned int exponent) {
// ...
}
Run Code Online (Sandbox Code Playgroud) 我希望此代码是可能的。
template<typename K, typename T, typename Comparer>
class AVLTree
{
...
void foo() {
...
int res = Comparer::compare(key1, key2);
...
}
...
};
Run Code Online (Sandbox Code Playgroud)
具体来说,我想强制Comparer类具有一个static int compare(K key1, K key2)功能。我当时正在考虑使用推导,但是找不到任何适用于模板的想法。
谢谢。
如果一个类有一个具有给定签名的构造函数,我如何编译时检测?具体来说,我想做以下事情:
class Archive
{
// (...)
template <typename T>
T Read()
{
if constexpr(HasUnarchiveConstructor<T>())
{
return T(*this); // constructor accepts reference to Factory
}
else
{
T t;
Unarchive(*this, t); // use stand alone function instead. (if this is not available either, compiling fails)
return t;
}
}
}
Run Code Online (Sandbox Code Playgroud)
有许多用于检测具有特定签名的功能的源.但是我无法将这些转换为构造函数. 源1 源2 源3等等.
从我发现的源代码中我编译了以下内容以检测函数是否具有plus运算符:
template<typename T>
using HasUnarchiveConstructorImpl = decltype(std::declval<T>() + std::declval<T>());
template< typename T >
using HasUnarchiveConstructor = std::is_detected<HasUnarchiveConstructorImpl, T>;
Run Code Online (Sandbox Code Playgroud)
如何将其扩展到我想要执行的检查?或者我怎么能以不同的方式做到这一点?