C++ 如何防止std::is_可构造中的隐式转换

C++ 如何防止std::is_可构造中的隐式转换,c++,implicit-conversion,constexpr,typetraits,if-constexpr,C++,Implicit Conversion,Constexpr,Typetraits,If Constexpr,比如说,我有几个不同的课程: class constructible_from_float { public: constructible_from_float(float); }; class constructible_from_double { public: constructible_from_double(double); }; class constructible_from_long_double { public: constructible_fr

比如说,我有几个不同的课程:

class constructible_from_float {
public: 
    constructible_from_float(float);
};
class constructible_from_double {
public: 
    constructible_from_double(double);
};
class constructible_from_long_double {
public: 
    constructible_from_long_double(long double);
};
然后我想根据它们的构造类型做一些事情(简化示例):

我知道这种行为的原因是类型之间的隐式转换。 是否有合法的(至少在三种主要编译器上可用:
msvc
gcc
clang
)方法来强制编译器区分这些类型

我不允许更改类(
constructible\u from\u float
等),但可以做其他任何事情。
编译器的稳定版本提供的任何东西都可以(包括代码> C++ 2a < /COD>)。你必须愚弄C++编译器,向你揭示它想要使用的隐式转换,然后使用sFIFE从它的脚下拉出地毯,并且不能实例化模板,但是SFANE,所以它不是一个错误。
#include <type_traits>
#include <iostream>

class constructible_from_float {
public:
    constructible_from_float(float);
};
class constructible_from_double {
public:
    constructible_from_double(double);
};
class constructible_from_long_double {
public:
    constructible_from_long_double(long double);
};


template<typename T> class convertible_only_to {

public:
    template<typename S, typename=std::enable_if_t<std::is_same_v<T,S>>>
    operator S() const
    {
        return S{};
    }
};


template <typename T>
constexpr int foo() {
    if constexpr (std::is_constructible<T,
              convertible_only_to<float>>::value) {
            return 1;
    } else
    if constexpr (std::is_constructible<T,
              convertible_only_to<double>>::value) {
            return 2;
        } else
    if constexpr (std::is_constructible<T,
              convertible_only_to<long double>>::value) {
            return 3;
    } else
        return -1;
}

struct not_constructible_from_anything {};

int main()
{
    std::cout << foo<constructible_from_float>() << std::endl;
    std::cout << foo<constructible_from_double>() << std::endl;
    std::cout << foo<constructible_from_long_double>() << std::endl;
    std::cout << foo<not_constructible_from_anything>() << std::endl;

    return 0;
}
#包括
#包括
类可构造的\u来自\u float{
公众:
从浮点数(float)可构造浮点数;
};
类可构造的\u from\u double{
公众:
可从双(双)码构造双(双)码;
};
类可构造的\u来自\u long\u double{
公众:
可从长双圈(长双圈)构造的长双圈;
};
模板类仅可转换为{
公众:
模板
运算符S()常量
{
返回S{};
}
};
模板
constexpr int foo(){
如果constexpr(std::is_constructible::value){
返回1;
}否则
如果constexpr(std::is_constructible::value){
返回2;
}否则
如果constexpr(std::is_constructible::value){
返回3;
}否则
返回-1;
}
结构不可从任何{}构造;
int main()
{

这正是我想要的。谢谢。
[[maybe_unused]] auto float_result = foo<constructible_from_float>();
[[maybe_unused]] auto double_result = foo<constructible_from_double>();
[[maybe_unused]] auto long_double_result = foo<constructible_from_long_double>();
#include <type_traits>
#include <iostream>

class constructible_from_float {
public:
    constructible_from_float(float);
};
class constructible_from_double {
public:
    constructible_from_double(double);
};
class constructible_from_long_double {
public:
    constructible_from_long_double(long double);
};


template<typename T> class convertible_only_to {

public:
    template<typename S, typename=std::enable_if_t<std::is_same_v<T,S>>>
    operator S() const
    {
        return S{};
    }
};


template <typename T>
constexpr int foo() {
    if constexpr (std::is_constructible<T,
              convertible_only_to<float>>::value) {
            return 1;
    } else
    if constexpr (std::is_constructible<T,
              convertible_only_to<double>>::value) {
            return 2;
        } else
    if constexpr (std::is_constructible<T,
              convertible_only_to<long double>>::value) {
            return 3;
    } else
        return -1;
}

struct not_constructible_from_anything {};

int main()
{
    std::cout << foo<constructible_from_float>() << std::endl;
    std::cout << foo<constructible_from_double>() << std::endl;
    std::cout << foo<constructible_from_long_double>() << std::endl;
    std::cout << foo<not_constructible_from_anything>() << std::endl;

    return 0;
}