Перегрузить метод способом, который генерирует ошибку компилятора при вызове с временным - PullRequest
0 голосов
/ 25 октября 2018

Возможно, этот фрагмент кода лучше всего проиллюстрирует мои намерения:

#include <array>

template <size_t N>
void f(std::array<char, N> arr)
{
}

template <size_t N>
void f(std::array<char, N>&& arr)
{
    static_assert(false, "This function may not be called with a temporary.");
}

f() должен компилироваться для lvalues, но не для rvalues.Этот код работает с MSVC, но GCC срабатывает на static_assert, хотя эта перегрузка никогда не вызывается.

Так что мой вопрос двоякий: как правильно выразить свои намерения с помощью современного C ++ и почемукомпилятор оценивает static_assert в «мертвой» перегрузке шаблона, которая никогда не создавалась?

Попробуйте онлайн: https://godbolt.org/z/yJJn7_

Ответы [ 4 ]

0 голосов
/ 25 октября 2018

В дополнение к другим ответам, я хотел бы отметить, что в Стандартной библиотеке есть пример, который точно соответствует тому, что хочет OP - std::addressof:

template<class T>
constexpr T* addressof(T&) noexcept;

template<class T>
const T* addressof(const T&&) = delete;
0 голосов
/ 25 октября 2018

Достаточно просто.

template <size_t N>
void f(const std::array<char, N>&& arr) = delete;
0 голосов
/ 25 октября 2018

Один из вариантов - удалить static_assert и пометить функцию как удаленную.Затем, если вы вызовете его с помощью значения r, вы получите сообщение об ошибке, в котором говорится, что вы пытаетесь использовать удаленную функцию

template <size_t N>
void f(const std::array<char, N>& arr)
{

}

template <size_t N>
void f(const std::array<char, N>&& arr) = delete; // used const here just in case we get a const prvalue

int main()
{
    std::array<char, 3> foo{};
    f(foo);
    //f(std::array<char, 3>{}); // error
    return 0;
}
0 голосов
/ 25 октября 2018

Возможно использование только одной функции, которая получает ссылку на неконстантный объект:

template<size_t N> void f(std::array<char, N>& arr);

Больше не требуется перегрузок.

Это правило равно обеспечивается спецификацией языка. Однако компилятор Visual C ++ имеет расширение, позволяющее передавать значения в такую ​​функцию.

...