如何避免“隐式”调用std :: pair中的单参数构造函数 [英] How to avoid 'implicit' calling of a one-parameter constructor in std::pair
问题描述
原始的问题是如何使用 std :: map< std :: wstring,std :: wstring> >
,因为相等类型的键和值极易出错。所以我决定为这个值创建一个简单的包装:
The original problem was how to work with std::map<std::wstring, std::wstring> >
in a secure way because equal types of the key and the value are extremely error-prone. So I decided to create a simple wrapper for the value:
struct ComponentName
{
std::wstring name;
// I want to prohibit any implicit string-ComponentName conversions!!!
explicit ComponentName(const std::wstring& _name) : name(_name)
{
}
bool operator<(const ComponentName& item_to_compare) const
{
return name < item_to_compare.name;
}
};
typedef std::map<std::wstring, ComponentName> component_names_map;
但是下面的代码工作得很好!
But the following code works well!
component_names_map component_names;
// Are you sure that ComponentName's constructor cannot be called implicitly? ;)
component_names_map::value_type a_pair = std::make_pair(L"Foo", L"Bar");
这是因为 std :: pair< std :: wstring,ComponentName> ;
复制构造函数显式使用ComponentName的字符串来赋值 std :: pair< std :: wstring,std :: wstring>
。这是一个绝对合法的操作。但是它看起来像是ComponentName构造函数的一个隐含调用。
It works because the std::pair<std::wstring, ComponentName>
copy constructor explicitly uses the string contructor of the ComponentName to assign the std::pair<std::wstring, std::wstring>
instance. It's an absolutely legal operation. However it looks as an 'implicit' call of the ComponentName constructor.
所以我知道问题的原因,但是如何避免这个 $ c> wstring-ComponentName 转换?
最简单的方法是不声明字符串构造函数,但它使ComponentName初始化不方便。
So I know the reason of the problem, but how can I avoid this 'implicit' wstring-ComponentName
conversion?
The simplest way is to not declare the string constructor, but it makes ComponentName initialization inconvenient.
推荐答案
可以合法地通过为您的类型添加 std :: pair
的部分专业化:
I think you can legally do this by adding a partial specialisation of std::pair
for your type:
namespace std {
template <typename T>
struct pair<T,ComponentName> {
typedef T first_type;
typedef ComponentName second_type;
T first;
ComponentName second;
// The rest of the pair members:
// ....
// Any trick you like to make it fail with assignment/construction from
// pair<std::wstring, std::wstring>
};
}
说明:
§17.6.4.2.1列出了 std
命名空间中专业化的基本规则:
§ 17.6.4.2.1 sets out the basic rules for specialisations in the std
namespace:
程序可以为任何标准库
模板添加模板到命名空间std,如果声明依赖于
用户定义的类型,并且专业化满足标准库
对原始模板的要求,并没有明确
禁止
"A program may add a template specialization for any standard library template to namespace std only if the declaration depends on a user-defined type and the specialization meets the standard library requirements for the original template and is not explicitly prohibited"
我看不到任何明确的禁止,
I can't see any explicit prohibition that would rule this particular case out, provided you filled out the rest of the class, within the bounds of § 20.3 .
或者,可能的话,法律方法:
Alternative, possibly legal approach:
专门化 std :: is_constructible< ComponentName,std :: wstring>
c> value 为false。这是作为 std :: pair
的不同类型的赋值运算符和复制构造函数的要求列出的。我无法看到任何禁止快速扫描这个,但我找不到任何要求实施必需以检查要求。
Specialize std::is_constructible<ComponentName, std::wstring>
such that value
is false. This is listed as a requirement of both the assignment operator and the copy constructor for std::pair
s of different types. I can't see any prohibitions from a quick scan of this either, but I can't find anything saying that implementations are required to check the requirements.
这篇关于如何避免“隐式”调用std :: pair中的单参数构造函数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!