Допустим, у нас есть такой класс с определяемым пользователем руководством по дедукции:
template<typename T, typename... Args>
struct Foo
{
Foo(Args&&...) { std::cout << "just Args: " << __PRETTY_FUNCTION__ << std::endl; }
Foo(Args&&..., T&&) { std::cout << "Args and T: " << __PRETTY_FUNCTION__ << std::endl; }
};
template<typename... Args>
Foo(Args&&...) -> Foo<Void, Args...>;
Теперь попробуем создать экземпляр этого класса: Foo foo { 10 };
. Какими будут выведенные аргументы шаблона и какой конструктор будет вызываться?
После некоторых экспериментов выясняется, что это зависит от компилятора. А именно, gcc 7 и clang 6 (из ствола), похоже, выбирают автоматическое руководство, создавая экземпляр T
с int
и Args
с пустым пакетом, поэтому вывод
Args and T: Foo<T, Args>::Foo(Args&& ..., T&&) [with T = int; Args = {}]
clang 5, с другой стороны, выбирает определяемое пользователем руководство:
just Args: Foo<Void, int>::Foo(Args &&...) [T = Void, Args = <int>]
Какой выбор правильный и как в этом случае можно использовать определяемое пользователем руководство по дедукции?
Полный пример доступен на wandbox.