Я пытаюсь написать класс, основанный на политике, который передает аргументы своему уникальному суперклассу, но также может принимать некоторые собственные аргументы. Проблема, с которой я сталкиваюсь, заключается в том, что компилятор, похоже, безоговорочно предпочитает второй конструктор, представленный ниже, перед лицом неявного преобразования - только с пакетом параметров - над первым, который я предпочитаю.
#include <utility>
#include <iostream>
template <class Super>
struct Base : public Super {
// 1
template <typename... Args,
typename = std::enable_if_t<std::is_constructible_v<Super, Args&&...>>>
explicit Base(unsigned long count, Args&&... args)
: Super(std::forward<Args>(args)...), count(count) {}
// 2
template <typename... Args,
typename = std::enable_if_t<std::is_constructible_v<Super, Args&&...>>>
explicit Base(Args&&... args) : Super(std::forward<Args>(args)...), count(0) {}
unsigned long count;
};
struct A {
explicit A(unsigned long id) {}
A() {}
};
struct B {
explicit B(const char* cstring) {}
explicit B(unsigned long id, const char* cstring) {}
explicit B(unsigned long id, A a) {}
B() {}
};
int main() {
auto a1 = Base<A>(7); // selects 2, but I want 1
auto a2 = Base<A>(7ul); // selects 1
auto a3 = Base<A>(7, 10); // selects 1
auto b1 = Base<B>(4); // selects 1
auto b2 = Base<B>("0440"); // selects 2
auto b3 = Base<B>(4, "0440"); // selects 2, but I want 1
auto b4 = Base<B>(4, 4, "0440"); // selects 1
auto b5 = Base<B>(4, A()); // selects 2
std::printf("%lu %lu %lu\n", a1.count, a2.count, a3.count);
std::printf("%lu %lu %lu %lu %lu\n", b1.count, b2.count, b3.count, b4.count, b5.count);
return 0;
}
Вывод 0 7 7
в первой строке, но я хочу 7 7 7
, т.е. Base<A>(7)
должен выбирать первый конструктор, а не второй. То же самое для b3
.
sfinae для конструкторов позволяет компилятору выбирать 1, когда 2 не соответствует аргументам, но я хочу, чтобы он выбирал конструктор 1 каждый раз, когда он совпадает. В случае a1
неявное преобразование 7 из int
в unsigned long
вызывает выбор конструктора 2, что я также не понимаю, почему.
Как мне решить эту проблему?