请考虑以下事项:
<svg id="paper" ></svg>
<div id="workingArea">
<button onclick="calculateTransform()">Get Transform</button>
<div class="results">
Transform: <span class="transformResult"></span>
</div>
<button onclick="rotateText('add')">Rotate + 10 Degrees</button>
<button onclick="rotateText('sub')">Rotate - 10 Degrees</button>
</div>
这适用于:
console.clear();
var paper = Snap("#paper");
var t = paper.text(0, 0, "SnapSVG is Awesome !");
//Translate to 250, 250 & Scale by 2 & 45Deg Rotate
t.transform('T250,250 S2 R45');
// Enable Drag
t.drag();
var calculateTransform = function() {
var currentTransform = t.transform().string;
console.log('test', currentTransform)
$('.results .transformResult').html(currentTransform)
}
var rotateText = function(op) {
// Read Current Rotate Value here.
var rotateVal = 0;
// add/Subtract based on option
if(op == 'add'){
rotateVal += 10;
}else if(op == 'sub') {
rotateVal -= 10;
}
// Calculate newTransform here.
var newTransform = 'T250,250 R' + rotateVal;
// Update object's rotation here.
t.attr({transform: newTransform });
}
其中template<typename T>
struct S
{
typedef M< &T::foo > MT;
}
是某种功能
如何修改S<Widget> SW;
的定义以允许以下内容:
Widget::foo()
答案 0 :(得分:2)
您需要的是以下类型转换。
T
,返回T
T *
,返回T
标准库已经在std::remove_pointer
中为我们实现了这一点(尽管你自己并不难)。
有了这个,你可以写
using object_type = std::remove_pointer_t<T>;
using return_type = /* whatever foo returns */;
using MT = M<object_type, return_type, &object_type::foo>;
关于您还希望使用智能指针的评论,我们必须重新定义类型转换。
smart_ptr<T>
,返回smart_ptr<T>::element_type
,应为T
T *
,返回T
T
,返回T
本身为此,我们必须编写自己的元函数。至少,我不知道标准库中的任何内容会对此有所帮助。
我们首先定义主template
(“其他”情况)。
template <typename T, typename = void>
struct unwrap_obect_type { using type = T; };
默认为void
的第二个(匿名)类型参数将在以后使用。
对于(原始)指针,我们提供以下部分特化。
template <typename T>
struct unwrap_obect_type<T *, void> { using type = T; };
如果我们停在这里,我们基本上会得到std::remove_pointer
。但我们将为智能指针添加额外的部分特化。当然,我们首先要定义“智能指针”是什么。出于此示例的目的,我们将使用名为typedef
的嵌套element_type
作为智能指针处理每个类型。根据需要调整此定义。
template <typename T>
struct unwrap_obect_type
<
T,
std::conditional_t<false, typename T::element_type, void>
>
{
using type = typename T::element_type;
};
第二个类型参数std::conditional_t<false, typename T::element_type, void>
是一种在C ++ 14中模拟std::void_t
的复杂方法。我们的想法是我们有以下部分类型函数。
T
类型,其中嵌套typedef
名为element_type
,返回void
因此,如果我们正在处理智能指针,我们将获得比主要template
更好的匹配,否则,SFINAE将从进一步的考虑中删除此部分专业化。
这是一个工作示例。 T.C.建议使用std::mem_fn
来调用成员函数。这使代码比我最初的例子更清晰。
#include <cstddef>
#include <functional>
#include <iostream>
#include <memory>
#include <string>
#include <utility>
template <typename ObjT, typename RetT, RetT (ObjT::*Pmf)() const noexcept>
struct M
{
template <typename ThingT>
static RetT
call(ThingT&& thing) noexcept
{
auto wrapper = std::mem_fn(Pmf);
return wrapper(std::forward<ThingT>(thing));
}
};
template <typename T, typename = void>
struct unwrap_obect_type { using type = T; };
template <typename T>
struct unwrap_obect_type<T *, void> { using type = T; };
template <typename T>
struct unwrap_obect_type<T, std::conditional_t<false, typename T::element_type, void>> { using type = typename T::element_type; };
template <typename T>
struct S
{
template <typename ThingT>
void
operator()(ThingT&& thing) const noexcept
{
using object_type = typename unwrap_obect_type<T>::type;
using id_caller_type = M<object_type, int, &object_type::id>;
using name_caller_type = M<object_type, const std::string&, &object_type::name>;
using name_length_caller_type = M<object_type, std::size_t, &object_type::name_length>;
std::cout << "id: " << id_caller_type::call(thing) << "\n";
std::cout << "name: " << name_caller_type::call(thing) << "\n";
std::cout << "name_length: " << name_length_caller_type::call(thing) << "\n";
}
};
class employee final
{
private:
int id_ {};
std::string name_ {};
public:
employee(int id, std::string name) : id_ {id}, name_ {std::move(name)}
{
}
int id() const noexcept { return this->id_; }
const std::string& name() const noexcept { return this->name_; }
std::size_t name_length() const noexcept { return this->name_.length(); }
};
int
main()
{
const auto bob = std::make_shared<employee>(100, "Smart Bob");
const auto s_object = S<employee> {};
const auto s_pointer = S<employee *> {};
const auto s_smart_pointer = S<std::shared_ptr<employee>> {};
s_object(*bob);
std::cout << "\n";
s_pointer(bob.get());
std::cout << "\n";
s_smart_pointer(bob);
}