SFINAE 关于 VS10 中的数组初始化

SFINAE on array initialization in VS10

关于cppreference/variant(4),转换构造函数描述如下:

Converting constructor. Constructs a variant holding the alternative type T_j that would be selected by overload resolution for the expression F(std::forward<T>(t)) if there was an overload of imaginary function F(T_i) for every T_i from Types... in scope at the same time, except that:

  • An overload F(T_i) is only considered if the declaration T_i x[] = { std::forward<T>(t) }; is valid for some invented variable x;
  • If T_i is (possibly cv-qualified) bool, F(T_i) is only considered if std:remove_cvref_t<T> is also bool.

因为我与 Visual Studio 2010 相关,但仍然想要一个标准变体,所以我自己实现了一个。我遇到的问题以及我在这里寻求解决方案的问题是如何在 VS10 中实现第一个要点?如果表达式

,如何丢弃虚函数 F(T_i) 的重载

T_i x[] = { std::forward<T>(t) };

格式不正确?

在 VS15 中我可以写:

template<class T> using array_t = T[];

template<class UserType, class T_i, class = void>
struct Single_FUN_T_i {
    using type = void(*)();
};

template<class UserType, class T_i>
struct Single_FUN_T_i<UserType, T_i,
    decltype( array_t<T_i>{ std::declval<UserType>() }, void() )> {
    //        ^^ Here I check whether T_i[]{ declval<T>() } compiles
    using type = T_i(*)(T_i);
};

但是在 VS10 中这不起作用,因为表达式 array_t<T_i>{ std::declval<UserType>() } 似乎不受支持(我知道别名模板也不起作用,但这不是问题)。

我认为这可能会让您更进一步。不使用数组初始化,而是使用 declval 实例化数组并尝试在其中插入元素。

// TestSfinae.cpp :此文件包含 'main' 函数。程序执行在那里开始和结束。 //

#include <iostream>
#include <utility>
#include <iostream>
#include <string>
#include <boost/utility/declval.hpp>

template<class A, class B, class = void>
struct X {
    std::string msg;
    X():msg("Fail"){};
};

template<class A, class B>
struct X<A, B, decltype(boost::declval<A[]>()[0]=boost::declval<B>(), void()) > 
{
    std::string msg;
    X():msg("Pass"){};
};

int main(){
    X<int,int> x;
    std::cerr << x.msg << std::endl;;

    X<int,std::string> y;
    std::cerr << y.msg << std::endl;;

}

结果如预期

Pass
Fail

不幸的是,我认为我无法用 VS10 解决这个问题。这是因为 the aggregate initilization T object[]{args...} 仅适用于 C++11 而不是 VS10 的一部分。要在聚合初始化上执行 SFINAE,我不能写 decltype(T x[]= {arg}) 但必须像我的示例那样写 decltype(array_t<T>{arg})