SFINAE по инициализации массива в VS10 - PullRequest
0 голосов
/ 22 февраля 2019

Вкл. cppreference / option (4) конструктор преобразования описывается следующим образом:

Конструктор преобразования.Создает вариант, содержащий альтернативный тип T_j, который был бы выбран разрешением перегрузки для выражения F(std::forward<T>(t)), если бы была перегрузка мнимой функции F(T_i) для каждого T_i из Types... в области действия одновременно,за исключением того, что:

  • Перегрузка F(T_i) рассматривается только в том случае, если объявление T_i x[] = { std::forward<T>(t) }; действительно для некоторой изобретенной переменной x;
  • Если T_i (возможно cv)bool, F(T_i) считается, только если std:remove_cvref_t<T> также 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>() } не поддерживается (я знаю, что шаблон псевдонимов также не будет работать, но это не проблема).

Ответы [ 2 ]

0 голосов
/ 27 февраля 2019

К сожалению, я думаю, что не могу решить эту проблему с VS10.Это связано с тем, что совокупная инициализация T object[]{args...} доступна только с C ++ 11 и еще не является частью VS10.И чтобы выполнить SFINAE при инициализации агрегата, я не могу написать decltype(T x[]= {arg}), но должен был бы написать decltype(array_t<T>{arg}), как в моем примере.

0 голосов
/ 26 февраля 2019

Я думаю, что это может продвинуть вас дальше.Вместо инициализации массива используйте 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
...