有条件地编译基于数字模板参数的转换运算符

ein*_*ica 2 c++ templates class typecast-operator

我有template <bool P> class Foo很多代码.我希望能够将Foo<true>'s转换成Foo<false>'s,即有一个operator Foo<false>()方法.但是编译器不喜欢Foo存在的这种方法,它只喜欢它Foo<true>,并且警告"如何不调用"运算符进行隐式或显式转换"(GCC 5.4.x)

似乎我不能使用SFINAE:std::enable_if适用于类型; 我试过的一个价值变量(真正的案例有一个value而不是一个type成员)也没有帮助.

我怎样才能让这个运算符只被编译Foo<false>(除了专门化Foo<false>不同和复制我的所有代码)?

到目前为止,我最好的尝试是:

template <bool P> class Foo {
    // etc. etc.
    template <bool OtherValue>
    operator Foo<OtherValue>()
    {
        static_assert(OtherValue, "You should not be using this conversion!");
        // conversion code here
        return Foo<false>(args,go,here);
    }
}
Run Code Online (Sandbox Code Playgroud)

Vit*_*meo 5

我怎样才能让这个运算符只被编译Foo<false>(除了专门化Foo<false>不同和复制我的所有代码)?

template <bool P> 
struct Foo 
{
    template <bool P2 = P, typename = std::enable_if_t<P2 == true>>
    operator Foo<false>()
    {
        return {};
    }
};
Run Code Online (Sandbox Code Playgroud)

使用P2 = P延迟enable_if_t时,实际使用转换运算符时的to 的评估(而不是类实例化).


如果我们试着简单地写:

template <typename = std::enable_if_t<P == true>>
operator Foo<false>()
{
    return {};
}
Run Code Online (Sandbox Code Playgroud)

std::enable_if_t<P == true>将在Foo<P>实例化期间进行评估,因为在实例化成员函数时不会发生替换.Foo实例化时会发生替换- 因此无法进行SFINAE (因为尚未设置任何重载决策).

通过添加bool P2 = P默认参数,我们将替换延迟到转换运算符的实例化.这在重载解决期间发生,因此可以发生SFINAE.

这个答案比我更好地解释了它:https://stackoverflow.com/a/13401982/598696