C++ 为什么带有一个元素的带括号的init列表的类型会切换到元素本身的类型?

C++ 为什么带有一个元素的带括号的init列表的类型会切换到元素本身的类型?,c++,c++11,initializer-list,typetraits,list-initialization,C++,C++11,Initializer List,Typetraits,List Initialization,在下面的代码中,使用参数{1,2}对实例b的成员函数F的调用编译并调用b::F(std::initializer_list)。但是如果我从带括号的init列表中删除一个元素并只使用{1},我会得到一个错误 9:错误:调用“begin(int)”时没有匹配的函数 使用type=decltype(std::begin(std::declval()) 我不明白为什么编译器要查找begin(int),而不是begin(初始值设定项列表) 我一直在玩这个,我在clang和g++上都遇到了同样的错误。我错过

在下面的代码中,使用参数{1,2}对实例b的成员函数F的调用编译并调用
b::F(std::initializer_list)
。但是如果我从带括号的init列表中删除一个元素并只使用{1},我会得到一个错误

9:错误:调用“begin(int)”时没有匹配的函数
使用type=decltype(std::begin(std::declval())

我不明白为什么编译器要查找
begin(int)
,而不是
begin(初始值设定项列表)

我一直在玩这个,我在clang和g++上都遇到了同样的错误。我错过了什么

#include <type_traits>
#include <iterator>

template< bool B, class T = void >
using enable_if_t = typename std::enable_if<B,T>::type;

template <typename T>
struct mytrait {
  using type = decltype(std::begin(std::declval<T>()));
  };

template <typename T>
class A {
  public:
  template <typename TA, typename =
     enable_if_t<std::is_same<T, typename mytrait<TA>::type>::value>>
      A(TA &&){}
};

class B
{
  public:
    void F(A<int>);
    void F(std::initializer_list<int>);
};

int main()
{
  B b;

  b.F({1,2});    // compiles fine
#if 0
  b.F({1});      // causes mytrait<int>::type to be examined, 
                 // not mytrait<std::initializer_list<int>>::type
#endif 
}
#包括
#包括
模板
使用enable_if_t=typename std::enable_if::type;
模板
结构mytrait{
使用type=decltype(std::begin(std::declval());
};
模板
甲级{
公众:
模板
A(TA&&{}
};
B类
{
公众:
F(A)项无效;
无效F(标准:初始值设定项列表);
};
int main()
{
B B;
b、 F({1,2});//编译精细
#如果0
b、 F({1});//导致检查mytrait::type,
//不是mytrait::type
#恩迪夫
}

好吧,我想我找到了答案。当编译器看到
b.F({1})
时,它试图找出要调用的F重载。它看到有一个重载接受
A
,因此,通过,它尝试查看是否可以使用
A{1}
构造
A
。文本
1
的类型是int。因此TA被推断为int。
mytrait
尝试确定
decltype(std::begin(declval())
,int类型没有std::begin,因此编译器出错

对于
b.F({1,2})
,没有接受两个输入的
A
构造函数,因此甚至不尝试列表初始化

看起来我可以通过将mytraits模板声明更改为

template <typename T, typename = decltype(std::begin(std::declval<T>()))>
struct mytraits {...};
模板
结构mytraits{…};
这似乎是在使用SFINAE使mytrait::type成为替换失败。

因为“统一初始化”:-)