Неустойчивая перегрузка?

Я слышал, что volatile является фактором перегрузки как const.

Если функция перегружена изменчивым параметром, когда называется volatile-version?

Я не могу представить ситуацию, когда вызывается volatile-версия.  

Ответ 1

Volatile может применяться к параметрам, но это не является фактором перегрузки при применении непосредственно к параметру. Однако можно использовать его для различения типов параметра. Например, это законно:

void f(int &p) {}; //reference to int
void f(volatile int &p) {}; //reference to volatile int

Это не:

void f(int p) {};
void f(volatile int p) {};

Причина в том, что в первом примере ссылка не является изменчивой, а целой. Во втором примере оба типа являются целыми числами и, следовательно, одного и того же типа.

Существуют также летучие методы. Они сродни объявлению this неустойчивым. Поскольку this является указателем, а не самим содержащим типом, это также является законным:

void c::f(int p) {};
void c::f(int p) volatile {};

Это все равно, что для перегрузки на const.

Эта важная часть стандарта С++ - это §13.1 Перегружаемые объявления. Из С++ 11 черновик n3290:

Объявления параметров, которые отличаются только наличием или отсутствием константы и/или летучих, эквивалентны. То есть, константные и неустойчивые типы-спецификаторы для каждого типа параметра игнорируются при определении того, какая функция объявляется, определяется или вызывается. [Пример:

typedef const int cInt;
int f(int);
int f(const int);          // redeclaration of f(int)
int f(int) { /* ... */ }   // definition of f(int)
int f(cInt) { /* ... */ }  // error: redefinition of f(int)

- конец примера]

Только константные и неустойчивые типы-спецификаторы на самом внешнем уровне спецификации типа параметра игнорируются таким образом; const и volatile-спецификаторы, скрытые в спецификации типа параметра, являются значительными и могут использоваться для различения описаний перегруженных функций 124. В частности, для любого типа T, pointer to T, pointer to const T и pointer to volatile T рассматриваются различные типы параметров, такие как reference to T, reference to const T и reference to volatile T.

124) Когда тип параметра включает в себя тип функции, например, в случае типа параметра, который является указателем на функцию, const и volatile-спецификаторы на внешнем уровне спецификаций типа параметра для внутреннего типа функции также игнорируется.

Ответ 2

Вот пример:

#include <iostream>

struct A {
    void foo() {
        std::cout << "in non-volatile" << std::endl;
    }
    void foo() volatile {
        std::cout << "in volatile" << std::endl;
    }
};

int main()
{
    A a;
    a.foo();
    volatile A b;
    b.foo();
}

b.foo() вызовет перегрузку volatile. Если struct A не имеет изменчивой перегрузки для foo, b.foo() будет недействительным.

Ответ 3

Напишите тестовую программу, чтобы узнать.

void func(const int& a)
{
    std::cout << "func(const)" << std::endl;
}

void func(const volatile int& a)
{
    std::cout << "func(const volatile)" << std::endl;
}

int main()
{
    const int a = 0;
    const volatile int b = 0;
    func(a);
    func(b);
    system("pause");
    return 0;
}

выведет:

func(const)
func(const volatile)