Здесь работает запись tie
вместо std::tie
из-за поиска, зависящего от аргумента:
std::tuple<int, std::string> tup = std::make_tuple<int, std::string>(1, "a");
int i;
std::string str;
tie(i, str) = tup;
Но почему make_tuple
требует std::
?
Поскольку ни 1
, ни "a"
не находятся в пространстве имен std
, попробуйте make_tuple(1, std::string("a"))
.
Они не одинаковы; "a"
— это const char[2]
, а str
— это std::string
.
@wohlstad: C++20 потребуется для ADL с <..>
(если OP также не определяет некоторые make_tuple<..>
в глобальном пространстве имен).
@Jarod42 хорошая мысль. Я добавлю это к своему ответу.
Основная идея std::make_tuple()
— избегать явного указания параметров шаблона.
Чтобы ADL (поиск, зависящий от аргументов) работал, вам нужен один из аргументов в пространстве имен std
.
Это имеет место при вызове tie
(str
— это std::string
), но не при вызове make_tuple
(ни 1
, ни "a"
не являются).
Вы можете использовать ADL, указав std::string
следующим образом:
//-----------------------------------------------------------------vvvvvvvvvvv--------
std::tuple<int, std::string> tup = make_tuple<int, std::string>(1, std::string{ "a" });
Примечание:
Для приведенного выше кода, который пытается максимально приблизиться к вашей версии, требуется C++20 (где явные аргументы шаблона не препятствуют ADL).
Однако эта версия, которая также короче, работает в более ранних версиях C++:
std::tuple<int, std::string> tup = make_tuple(1, std::string{ "a" });
Есть ли какая-то конкретная причина, по которой параметры типа функции не используются в ADL?
Именно так и указано (можно посмотреть по ссылке, которую я разместил). Я не знаю причин этого. Это хорошая статья - можете посмотреть, если я что-то пропустил о рациональности. Похоже, что изначально ADL предназначался для решения конкретной, более узкой задачи.
Чтобы ADL работал, вам нужно, чтобы один из аргументов находился в пространстве имен. Это сработает:
std::tuple<int, std::string> tup = make_tuple<int, std::string>(1, std::string{ "a" });
.