Условно включить оператор конверсии с SfinaeC++

Программы на C++. Форум разработчиков
Ответить
Anonymous
 Условно включить оператор конверсии с Sfinae

Сообщение Anonymous »

[Примечание: я застрял с C ++ 17.] < /p> У меня есть шаблон класса, который создается в довольно большом количестве типов (~ 25). Некоторые из них могут правильно преобразовать друг друга, и я хотел бы, чтобы это произошло неявно. Но я не хочу, чтобы компилятор пытался преобразовать другие и обрести ошибки. < /P>
Моя идея состояла в функция, которая на самом деле делает преобразование; Эта свободная функция будет определена только для типов, где должно произойти конверсия. Вот простой пример: < /p>

Код: Выделить всё

#include 

template 
class Template;

class SourceType {};
class TargetType {};
class SpectatorType {};

// forward-declare the convert() so that the function template can look at it
const Template & convert(const Template &);

template 
class Template
{
public:
template 
operator const U& () const { return convert(*this); }
};

// need the Template class template to be defined
// before this function is defined because we'll need to use its members
const Template & convert(const Template &)
{
// obviously not a real implementation
return *new Template();
}

// function to try the implicit conversion with
void TestFunc(const Template & t)
{}

int main()
{
Template src;
Template spec;

// try to explicitly call the conversion operator, should succeed
src.operator const Template&();

// this should succeed: const Template& should be implicitly convertible to const Template&
TestFunc(src);

// this should fail: const Template& != const Template& and there's no implicit conversion
TestFunc(spec);

return 0;
}

К сожалению, это не работает (попробуйте: https://godbolt.org/z/xaazsgc8c). С -wall , GCC 13.3 говорит мне, что есть бесконечная рекурсия:

Код: Выделить всё

sfinae-conv-op2.cpp: In member function ‘Template::operator const U&() const [with U = Template; T = TargetType]’:
sfinae-conv-op2.cpp:19:5: warning: infinite recursion detected [-Winfinite-recursion]
19 |     operator const U& () const { return convert(*this); }
|     ^~~~~~~~
sfinae-conv-op2.cpp:19:48: note: recursive call
19 |     operator const U& () const { return convert(*this); }
|                                         ~~~~~~~^~~~~~~
(и если я проигнорирую это и запускаю программу, это, как вы могли ожидать Он может построить для себя оператора конверсии, если он может вызвать конверт (const template ) , поэтому он пытается использовать свой оператор конверсии для преобразования Шаблон к шаблону (неправильный путь)! Затем, конечно, ему необходимо преобразовать sourcetype в TargetType , и мы ходим в круглый. Оператор преобразования неправильного направления из набора перегрузки (изменения от предыдущего в Bold < /strong>): < /p>

Код: Выделить всё


#include 

template 
class Template;

class SourceType {};
class TargetType {};
class SpectatorType {};


// disallow conversion by default
template 
const Template & convert(const Template &) { static_assert(false, "Not allowed"); }

// explicitly opt-in for relevant types
template 
const Template & convert(const Template &);

// type trait for detecting that the class has a nested `type` type
template
struct has_type_member : std::false_type {};

template 
struct has_type_member : std::true_type {};
[/b][b]
template 
class Template
{
public:
template [/b][b]        operator const U& () const { return convert(*this); }

using type = T;[/b]
};

// need the Template class template to be defined
// before this function is defined because we'll need to use its members
const Template & convert(const Template &)
{
// obviously not a real implementation
return *new Template();
}

void TestFunc(const Template & t)
{}

int main()
{
Template src;
Template spec;

// try to explicitly call the conversion operator, should succeed
src.operator const Template&();

// this should succeed: SourceType should be implicitly convertible to TargetType
TestFunc(src);

// this should fail: there's no implicit conversion
TestFunc(spec);

return 0;
}

Но по причинам, которые я не могу понять, это тоже не работает (https://godbolt.org/z/8me79jmrh); Попытка преобразовать неправильный путь все еще происходит, и я все еще становлюсь в бесконечной рекурсии.>

Подробнее здесь: https://stackoverflow.com/questions/794 ... ith-sfinae
Ответить

Быстрый ответ

Изменение регистра текста: 
Смайлики
:) :( :oops: :roll: :wink: :muza: :clever: :sorry: :angel: :read: *x)
Ещё смайлики…
   
К этому ответу прикреплено по крайней мере одно вложение.

Если вы не хотите добавлять вложения, оставьте поля пустыми.

Максимально разрешённый размер вложения: 15 МБ.

Вернуться в «C++»