答案 0 :(得分:25)
答案 1 :(得分:1)
我读过很多关于不可复制性的评论。许多人认为它不应该是不可复制的,因为我们不能将它作为参数传递给需要密钥的函数。有些人甚至对此感到惊讶。好吧它真的不应该,并且显然与一些Visual C ++编译器有关,因为我之前有相同的怪异但不再使用Visual C ++ 12(Studio 2013)。
但事实上,我们可以通过“基本”不可复制性来增强安全性。 Boost版本太多了,因为它完全阻止了复制构造函数的使用,因此对于我们需要的东西来说有点太多了。我们需要的是实际上将复制构造函数设为私有但不是没有实现。当然,实现将是空的,但它必须存在。我最近问过在这种情况下谁在调用copy-ctor(在这种情况下,在调用SomeKey
时调用了ProtectedMethod
的复制构造函数)。答案是,显然标准确保调用-ctor
的方法调用者确实看起来很合乎逻辑。因此,通过copy-ctor
隐私,我们允许朋友发挥作用(protected
Bar
和granted
Foo
)来调用它,从而允许Foo
调用ProtectedMethod
因为它使用值参数传递,但它也阻止任何人超出Foo
的范围。
通过这样做,即使同事开发人员尝试使用代码聪明地玩,他实际上必须让Foo
完成工作,另一个类将无法获得密钥,并且机会很多他几乎100%的时间都会以这种方式认识到他的错误(希望,否则他太过于初学者使用这种模式,或者他应该停止开发:P)。
答案 2 :(得分:1)
来自@GManNickG的精彩回答。学到了很多东西。试图让它工作,发现了一些错别字。为清楚起见,重复完整示例我的例子借用了#34;包含Key in Keys ..." @snk_kid发布的Check if C++0x parameter pack contains a type函数。
#include<type_traits>
#include<iostream>
// identify if type is in a parameter pack or not
template < typename Tp, typename... List >
struct contains : std::false_type {};
template < typename Tp, typename Head, typename... Rest >
struct contains<Tp, Head, Rest...> :
std::conditional< std::is_same<Tp, Head>::value,
std::true_type,
contains<Tp, Rest...>
>::type{};
template < typename Tp >
struct contains<Tp> : std::false_type{};
// everything is private!
template <typename T>
class passkey {
private:
friend T;
passkey() {}
// noncopyable
passkey(const passkey&) = delete;
passkey& operator=(const passkey&) = delete;
};
// what keys are allowed
template <typename... Keys>
class allow {
public:
template <typename Key>
allow(const passkey<Key>&) {
static_assert(contains<Key, Keys...>::value, "Pass key is not allowed");
}
private:
// noncopyable
allow(const allow&) = delete;
allow& operator=(const allow&) = delete;
};
struct for1;
struct for2;
struct foo {
void restrict1(allow<for1>) {}
void restrict2(allow<for1, for2>){}
} foo1;
struct for1 {
void myFnc() {
foo1.restrict1(passkey<for1>());
}
};
struct for2 {
void myFnc() {
foo1.restrict2(passkey<for2>());
// foo1.restrict1(passkey<for2>()); // no passkey
}
};
void main() {
std::cout << contains<int, int>::value << std::endl;
std::cout << contains<int>::value << std::endl;
std::cout << contains<int, double, bool, unsigned int>::value << std::endl;
std::cout << contains<int, double>::value << std::endl;
}