如何避免“隐式”调用std :: pair中的单参数构造函数 [英] How to avoid 'implicit' calling of a one-parameter constructor in std::pair

查看:83
本文介绍了如何避免“隐式”调用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::pairs 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆