Take the following class (C++17)
#include <variant>
template <typename Error, typename T>
class Optional
{
public:
constexpr Optional(T&& value)
: m_variant(std::forward<T>(value))
{}
private:
std::variant<Error, T> m_variant = Error{};
};
template <typename E, typename T>
Optional<E, T> MakeOptional(T&& val) { return Optional<E, T>{val}; }
enum class Error
{
ERROR,
OTHER_ERROR,
};
The following compiles just fine
Optional<Error, int> opt1{4};
auto opt3 = MakeOptional<Error>(7);
but this does not
Optional<Error> opt2{4}; // does not compile "too few template arguments for class template 'Optional'"
Is it possible to make the code above compile? It should be able to deduce the second template argument with the constructor's parameter just like MakeOptional() does.
CTAD is a "all or nothing".
See the note
Class template argument deduction is only performed if no template argument list is present. If a template argument list is specified, deduction does not take place.