Reputation: 22183
I have the template class Foo:
template<class T>
class Foo {
public:
Foo() = default;
Foo(const Foo&) = default;
Foo(Foo&&) = default;
Foo& operator=(Foo&&) = default;
Foo& operator=(const Foo&) = default;
template<class U, typename = typename std::enable_if<
!std::is_same<typename std::decay<U>::type, Foo>::value>::type>
Foo(U&&) {
}
};
int main() {
Foo<int> ff;
Foo<char> dd(ff); //here I want a compiler error
Foo<int> e(15); //it should work
return 0;
}
I'm trying to add constraints about template constructor, however this code compiles so I think I'm missing something, what's the proper way to add the enable_if?
Upvotes: 0
Views: 136
Reputation: 131950
In your main()
function, you're trying to construct a Foo<char>
from a Foo<int>
. A decay-based ctor will not work here, as Foo<A>
does not decay into Foo<B>
even if A
decays into B
. See the cppreference page on std::decay
for a detailed explanation of what it does, exactly.
Also, I would suggest avoiding explicit (templated) constructors from pre-decay types. If your argument too one of the copy or move constructors (from const Foo&
and Foo&&
respectively) decays into a Foo
, then those ctors should be enough. And if they somehow aren't, this implicit conversion that you're allowing for is probably more trouble than it's worth. It will certainly make your class more difficult to read and to adapt. You have, in fact, already seen it has led you to a minor bug :-P
Upvotes: 2
Reputation: 1
Besides the typo, you can also make use of the deleted function declaration as shown below:
#include <iostream>
#include <type_traits>
template<class T>
class Foo {
public:
Foo() = default;
Foo(const Foo&) = default;
Foo(Foo&&) = default;
Foo& operator=(Foo&&) = default;
Foo& operator=(const Foo&) = default;
template<typename K, typename = typename std::enable_if_t<!std::is_same_v<T, K>>>
Foo (Foo<K> const&) = delete;
};
int main() {
Foo<int> ff;
Foo<int> gg(ff); //THIS WORKS
//Foo<char> dd(ff); //THIS PRODUCES ERROR
return 0;
}
Upvotes: 0