add SkVptr()
I was wondering how feasible using this to make downcasts safe would be. These tests would need to build and pass on all our bots, at least. Change-Id: I1753ba58841bf6c17d6ac3af7374518356e1bb05 Reviewed-on: https://skia-review.googlesource.com/81180 Reviewed-by: Brian Salomon <bsalomon@google.com> Commit-Queue: Mike Klein <mtklein@chromium.org>
This commit is contained in:
parent
d34c4a3727
commit
0554d497f8
@ -274,6 +274,7 @@ tests_sources = [
|
||||
"$_tests/VkHeapTests.cpp",
|
||||
"$_tests/VkUploadPixelsTests.cpp",
|
||||
"$_tests/VkWrapTests.cpp",
|
||||
"$_tests/VptrTest.cpp",
|
||||
"$_tests/WindowRectanglesTest.cpp",
|
||||
"$_tests/WritePixelsTest.cpp",
|
||||
"$_tests/Writer32Test.cpp",
|
||||
|
24
src/core/SkVptr.h
Normal file
24
src/core/SkVptr.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#ifndef SkVptr_DEFINED
|
||||
#define SkVptr_DEFINED
|
||||
|
||||
#include <string.h>
|
||||
#include <type_traits>
|
||||
|
||||
// Experimentally, see if we can get at the vptr of objects with one.
|
||||
|
||||
template <typename T>
|
||||
static inline void* SkVptr(const T& object) {
|
||||
static_assert(std::has_virtual_destructor<T>::value, "");
|
||||
void* vptr;
|
||||
memcpy(&vptr, (const void*)&object, sizeof(vptr));
|
||||
return vptr;
|
||||
}
|
||||
|
||||
#endif//SkVptr_DEFINED
|
61
tests/VptrTest.cpp
Normal file
61
tests/VptrTest.cpp
Normal file
@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Copyright 2017 Google Inc.
|
||||
*
|
||||
* Use of this source code is governed by a BSD-style license that can be
|
||||
* found in the LICENSE file.
|
||||
*/
|
||||
|
||||
#include "SkMakeUnique.h"
|
||||
#include "SkVptr.h"
|
||||
#include "Test.h"
|
||||
|
||||
namespace {
|
||||
|
||||
struct Base {
|
||||
virtual ~Base() = default;
|
||||
virtual size_t val() const = 0;
|
||||
};
|
||||
|
||||
struct SubclassA : public Base {
|
||||
SubclassA(size_t val) : fVal(val) {}
|
||||
|
||||
size_t val() const override { return fVal; }
|
||||
|
||||
size_t fVal;
|
||||
};
|
||||
|
||||
struct SubclassB : public Base {
|
||||
SubclassB() {}
|
||||
|
||||
size_t val() const override { return 42; }
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
DEF_TEST(Vptr, r) {
|
||||
std::unique_ptr<Base> a = skstd::make_unique<SubclassA>(21),
|
||||
b = skstd::make_unique<SubclassB>(),
|
||||
c = skstd::make_unique<SubclassA>(22),
|
||||
d = skstd::make_unique<SubclassB>();
|
||||
|
||||
// These 4 objects all have unique identities.
|
||||
REPORTER_ASSERT(r, a != b);
|
||||
REPORTER_ASSERT(r, a != c);
|
||||
REPORTER_ASSERT(r, a != d);
|
||||
REPORTER_ASSERT(r, b != c);
|
||||
REPORTER_ASSERT(r, b != d);
|
||||
REPORTER_ASSERT(r, c != d);
|
||||
|
||||
// Only b and d have the same val().
|
||||
REPORTER_ASSERT(r, a->val() != b->val());
|
||||
REPORTER_ASSERT(r, a->val() != c->val());
|
||||
REPORTER_ASSERT(r, a->val() != d->val());
|
||||
REPORTER_ASSERT(r, b->val() != c->val());
|
||||
REPORTER_ASSERT(r, b->val() == d->val());
|
||||
REPORTER_ASSERT(r, c->val() != d->val());
|
||||
|
||||
// SkVptr() returns the same value for objects of the same concrete type.
|
||||
REPORTER_ASSERT(r, SkVptr(*a) == SkVptr(*c));
|
||||
REPORTER_ASSERT(r, SkVptr(*b) == SkVptr(*d));
|
||||
REPORTER_ASSERT(r, SkVptr(*a) != SkVptr(*b));
|
||||
}
|
Loading…
Reference in New Issue
Block a user