использование и перегрузка функции-члена шаблона базового класса?

В следующем, структура Y перегрузки Xфункция члена f, Обе перегрузки являются шаблонными функциями, но принимают разные аргументы (typename а также int), чтобы быть явно указано:

struct X
{
template <typename> static bool f() { return true; }
};

struct Y : public X
{
using X::f;
template <int> static bool f() { return false; }
};

int main()
{
std::cout << Y::f <void>() << " " << Y::f <0>() << std::endl;
}

Это печатает 1 0 используя gcc, как и ожидалось. Тем не менее, Clang (3.3) жалуется, что

[...] error: no matching function for call to 'f'
std::cout << Y::f <void>() << " " << Y::f <0>() << std::endl;
^~~~~~~~~~~
[...] note: candidate template ignored: invalid explicitly-specified argument
for 1st template parameter
template <int> static bool f() { return false; }
^

то есть виден только Yверсия я пробовал

using X::template f;

вместо этого, без успеха. То же самое происходит с нестатическими (шаблонными) функциями-членами. Так это ошибка?

6

Решение

Эта загадка была недавно объяснена мне в свете другого ответа.

Из канала IRC #clang:

[01:16:23] <zygoloid> Xeo: this is a weird corner of the language where clang conforms but the rule is silly
[01:16:31] <Xeo> ... really? :(
[01:16:45] <zygoloid> Xeo: when deciding whether a using-declaration is hidden, we're not allowed to look at the template-parameter-list (nor the return type, iirc)
[01:17:04] <zygoloid> so the derived class declaration of operator()(T) suppresses the using-declaration
[01:17:19] <Xeo> because it has the same signature / parameter types?
[01:17:40] <zygoloid> rigth

Обходной путь должен не определять f в классе, который uses производная версия. Вместо этого переместите его во вспомогательный вспомогательный класс (который, в данном случае, задает вопрос, какое определение, по вашему мнению, должно выиграть).

кредиты Спасибо @Xeo и людям в гостиная за раскопки этого «глупого правила»

6

Другие решения

Огромное разочарование вызывает то, что такое ограничение существует и не было ослаблено в C ++ 11 (может быть веская причина, но я не могу себе представить, почему). Я чувствую, что это разрушает всю концепцию иерархии классов.

Во всяком случае, вот один обходной путь, который я нашел. Я включил другую функцию g это нестатично, чтобы проиллюстрировать различия, потому что этот случай — мой главный интерес.

template <typename Y>
struct X
{
template <typename> static bool f() { return true; }
template <typename>        bool g() { return true; }

template <int I>
static bool f() { return Y::template _f <I>(); }

template <int I>
bool g()
{
return static_cast <Y&>(*this).template _g <I>();
}
};

class Y : public X <Y>
{
friend class X <Y>;
template <int> static bool _f() { return false; }
template <int>        bool _g() { return false; }
};

int main()
{
Y y;
std::cout << Y::f <void>() << " " << Y::f <0>() << std::endl;
std::cout << y. g <void>() << " " << y. g <0>() << std::endl;
}

Так что вся перегрузка происходит в базовом классе X, который реализует статический полиморфизм, принимая Y в качестве аргумента шаблона (к счастью, это уже имело место в моем проекте, поэтому я не меняю дизайн).

Настоящий YРеализации в частных функциях _f, _g, Этот дизайн хорош, когда есть много производных классов, таких как Y только с одной перегрузкой в ​​каждом и единственным базовым классом X с множеством других перегрузок. В этом случае массового дублирования кода избегают. Опять же, это так в моем проекте.

X не нужно знать возвращаемое значение этих функций. К сожалению, он должен знать тип возвращаемого значения: я пробовал, например, auto g() -> decltype(...) и снова это decltype работает только в gcc. Включение c ++ 1y пишет только один auto g() без конечной спецификации типа возврата, что позволяет избежать проблемы с decltype, Тем не мение, поддержка Clang для «возврата типа возврата для нормальных функций» (N3638) доступен только в текущей версии SVN.

До тех пор auto g() становится основным (и стандартным), нужно вычислить тип возвращаемого значения Yметоды, которые могут быть болезненными, особенно если есть много Ys.

Это все еще выглядит как беспорядок, но, по крайней мере, не полный.

2

По вопросам рекламы [email protected]