Reputation:
I would like to make a method conditionally const. That is, we have
template <bool isConst>
class A {
// stuff
};
depending on the value of the template parameter, either
void method() const;
or
void method();
appear in the body of A
.
My first thought was to try conditional types, but this does not work, for obvious reasons.
Upvotes: 1
Views: 167
Reputation: 1516
EDIT: This is only intended for interests' sake. I don't suggest actually doing this in a commercial product. Maybe in a personal project if you're trying out things.
Something you could do, which is a little hacky, is this:
template< bool OnlyConst >
class TestClass
{
struct Placeholder {};
public:
template< class T >
typename std::enable_if< OnlyConst && !std::is_same<T, Placeholder>::value, void >::type
MyFunc() const
{ std::cout << "Const version"; }
template< class T >
typename std::enable_if< !OnlyConst && !std::is_same<T, Placeholder>::value, void >::type
MyFunc()
{ std::cout << "Nonconst version"; }
};
The unfortunate bit is that the functions do need to be templated to use the enable_if, and if you have nothing to do with that template then the caller is still going to need to provide it so the compiler can 'use' it. You can't use a default template parameter for T either.
If you could find a use for T that would let the compiler automatically determine its type then it would work out well.
Right now you'd have to always give a value for T when calling:
test.MyFunc<void>(); // even though the void doesn't affect it at all
The placeholder struct is only there because SFINAE (at least on VS2012) seems to want T to be part of the determination of whether the function can be instantiated or not. So the is_same call is pretty much just for sticking some usage of T in the enable_if.
I have done a spot of testing with the above code in VS2012 and it seems to work.
Upvotes: 1
Reputation: 56883
The obvious solution is a specialization:
template<bool>
struct A
{
void method() const
{
std::cout << "const" << std::endl;
}
};
template<>
struct A<false>
{
void method()
{
std::cout << "non-const" << std::endl;
}
};
and in case you have more methods and don't want to duplicate them, make A
a base class A_base
and derive your A
from it. (I added this to the live example below)
Upvotes: 2