Да кажем, че имаме клас като този с дефинирано от потребителя ръководство за приспадане:
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 (от trunk) изглежда избират автоматичното ръководство, създавайки 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.