2013-04-21 2 views
1

Кто-нибудь знает, как определить конструктор с одним аргументом? Например, эта структура должна иметь отрицательный результат:SFINAE - Определить конструктор с одним аргументом

struct MyStruct 
{ 
    MyStruct(int x, int x2) : y(x) {} 
    int y; 
}; 

У меня здесь хороший чек SFINAE, чтобы увидеть, если класс или структуру в качестве конструктора с определенным количеством аргументов. Вот один для подсчета аргументов 3:

template <typename T> 
struct HasCtor3Args 
{ 
    struct Any { template <typename U> operator U(void); }; 

    template <typename U> 
    static int32 SFINAE(decltype(U(Any(), Any(), Any())) *); 

    template <typename U> 
    static int8 SFINAE(...); 

    static const bool value = sizeof(SFINAE<T>(NULL)) == sizeof(int32); 
}; 

Это, кажется, работает очень хорошо, так как Any структура может преобразовать в любые типы параметры должны быть. Однако проблема заключается в попытке обнаружить конструктор только с одним аргументом. Кажется, что проверка SFINAE всегда возвращает true из-за дефолта Any того же типа, что и T, тем самым обнаруживая конструктор копирования.

Редактирование и обновление: Я сделал несколько попыток, никто, кажется, идут ... Это было ближе всего я могу получить, но не работает, как это всегда возвращает истину. Идея состояла в том, чтобы попытаться получить копию конструктора для решения вместо первого «поймать всех» вызов:

template <typename T> 
struct HasCtor1Args 
{ 
    struct Any 
    { 
    template <typename U> 
    operator U() const; 
    }; 

    template <typename U> 
    static int32 SFINAE(decltype(U(Any())) *); 

    // Try to catch the copy ctor here 
    T MakeT(void); 
    template <typename U> 
    static int8 SFINAE(decltype(U(MakeT())) *); 

    template <typename U> 
    static int8 SFINAE(...); 

    static const bool value = sizeof(SFINAE<T>(NULL)) == sizeof(int32); 
}; 

Я также попытался использовать явное ключевое слово, вместе с = удалить функцию для C++ 11, то понял, что компилятор, который мне нужно использовать (Microsoft), не позволяет этого. Я также попытался использовать std :: enable_if в типе преобразования U, хотя я столкнулся с ошибкой, что параметры шаблона функции не могут быть дефолтны.

+0

О, и есть [ 'станд :: is_constructible'] (HTTP:.. // ан .cppreference.com/w/cpp/types/is_constructible) – dyp

+0

По какой-то причине он работает, когда оператор преобразования является явным: 'template Явный оператор U() const;'. Мне пришлось посмотреть это в Стандарт, но это может быть ошибка в g ++ 4.8. – dyp

+0

Хм, я не думаю, что использование такого явно будет работать на компиляторе Microsoft. – RandyGaul

ответ

2

Хотя критика n.m. все еще сохраняется, вот версия для обнаружения типа с только одна 1-параметрическая копия без перемещения. Он использует SFINAE для ограничения преобразования Any.

Примечание: Дополнительные ctors с аргументами по умолчанию приведет к неоднозначности (например my_type(int, double=0); Это очень ограниченное решение

#include <cstdint> 
#include <type_traits> 

template <typename T> 
struct HasCtor1Args 
{ 
    struct Any 
    { 
     template 
     < 
     typename U, typename SFINAE = 
      typename std::enable_if< false == std::is_same<U,T>::value, U >::type 
     > 
     operator U() const; 
    }; 

    template <typename U> 
    static int32_t SFINAE(decltype(U(Any())) *); 

    template <typename U> 
    static int8_t SFINAE(...); 

    static const bool value = sizeof(SFINAE<T>(nullptr)) == sizeof(int32_t); 
}; 


struct my_type 
{ 
    my_type(int); 
    my_type(my_type const&); 
}; 

int main() 
{ 
    static_assert(HasCtor1Args<my_type> :: value, "epic fail"); 
} 
+0

Ох, подождите, nvm ... тип параметра будет просто выведен как «Любой», я думаю. То же самое касается аргументов по умолчанию. Он не сработает для шаблона C (что-то ) '. – Xeo

+0

Я не понимаю, почему это не удастся. T просто становится типом Any. –

+0

@Johannes: Я вижу, мой новый комментарий выше. – Xeo

Смежные вопросы