初始化列表和转换为一切,构造顺序

时间:2015-10-15 02:55:53

标签: c++ type-conversion c++14 initializer-list

情况如:

#include <utility>
#include <typeinfo>
#include <iostream>

struct C1
{
    char const* str; 
    template <typename T> operator T() const { std::cout << "Convert to " << typeid(T).name() << "\n"; return {}; }
};

struct C2
{
    C2(C1 const&) { std::cout << "C2(C1)\n"; }
    C2(std::initializer_list<std::pair<char const*, int>>) { std::cout << "C2(list)\n"; }
};

int main()
{
    C1 c1{};
    C2 c2{c1};
}

输出表示正在调用C2(list)

我希望C2(C1)C1参数调用,但我需要std :: initializer list的参数保持可推导和可转换,我不能用variadic-templated版本替换它。我只想控制施工顺序,但这里// 2甚至不是模板。假设类型std :: pair可以在正常条件下反序列化。可以使用C ++ 14

2 个答案:

答案 0 :(得分:0)

您可以使用显式关键字来阻止构造函数进行隐式类型转换:

    explicit C2(std::initializer_list<std::pair<char const*, int>>) {} // 2

请参阅:What does the explicit keyword mean in C++?

答案 1 :(得分:0)

以下为样式C2(C1){...}选择({...})样式(在严格的C ++ 11标准中,对于({...})样式,它将选择第二种,因为C1是一个聚合,并且适用了特殊规则。对于更新的标准,情况不再是这种情况。)。这可以使第二个构造函数不再是初始化构造函数。

template<typename T>
struct id { typedef T type; };

struct C1 {
    char const* str; 
    template <typename T> operator T() const 
    { std::cout << "Convert to " << typeid(T).name() << "\n"; return {}; }
};

struct C2 {
    C2(C1);
    template<typename T = std::initializer_list<std::pair<char const*, int>>>
    C2(typename id<T>::type);
};

int main() {
    C1 c1{};
    C2 c2{c1};
    C2 c21({c1});
}