#include<string>
enum class type {
integer, string
};
template<type T>
struct foo_impl {
static constexpr bool is_valid = false;
typedef void Type;
};
template<>
struct foo_impl<type::integer> {
static constexpr bool is_valid = true;
typedef int Type;
};
template<>
struct foo_impl<type::string> {
static constexpr bool is_valid = true;
typedef std::string Type;
};
template<type T>
struct foo {
static_assert(foo_impl<T>::is_valid, "Not a valid type!");
using Type = typename foo_impl<T>::Type;
Type value;
foo(Type v) : value(std::move(v)) {}
friend foo operator|(type const& lhs, foo const& rhs) {
// do something
return rhs;
}
};
template<type T>
void test(foo<T>) {}
int main() {
using foo_int = foo<type::integer>;
using foo_string = foo<type::string>;
// what I want (they currently all don't compile)
test(type::integer | foo_int(10)); // ok
//test(type::integer | foo_int(std::string("hello"))); // error
test(type::string | foo_string(std::string("hello"))); // ok
//test(type::string | foo_string(10)); // error
}
I2luY2x1ZGU8c3RyaW5nPgoKZW51bSBjbGFzcyB0eXBlIHsKICAgIGludGVnZXIsIHN0cmluZwp9OwoKdGVtcGxhdGU8dHlwZSBUPgpzdHJ1Y3QgZm9vX2ltcGwgewogICAgc3RhdGljIGNvbnN0ZXhwciBib29sIGlzX3ZhbGlkID0gZmFsc2U7CiAgICB0eXBlZGVmIHZvaWQgVHlwZTsKfTsKCnRlbXBsYXRlPD4Kc3RydWN0IGZvb19pbXBsPHR5cGU6OmludGVnZXI+IHsKICAgIHN0YXRpYyBjb25zdGV4cHIgYm9vbCBpc192YWxpZCA9IHRydWU7CiAgICB0eXBlZGVmIGludCBUeXBlOwp9OwoKdGVtcGxhdGU8PgpzdHJ1Y3QgZm9vX2ltcGw8dHlwZTo6c3RyaW5nPiB7CiAgICBzdGF0aWMgY29uc3RleHByIGJvb2wgaXNfdmFsaWQgPSB0cnVlOwogICAgdHlwZWRlZiBzdGQ6OnN0cmluZyBUeXBlOwp9OwoKdGVtcGxhdGU8dHlwZSBUPgpzdHJ1Y3QgZm9vIHsKCXN0YXRpY19hc3NlcnQoZm9vX2ltcGw8VD46OmlzX3ZhbGlkLCAiTm90IGEgdmFsaWQgdHlwZSEiKTsKCQoJdXNpbmcgVHlwZSA9IHR5cGVuYW1lIGZvb19pbXBsPFQ+OjpUeXBlOwogICAgVHlwZSB2YWx1ZTsKICAgIAogICAgZm9vKFR5cGUgdikgOiB2YWx1ZShzdGQ6Om1vdmUodikpIHt9CgogICAgZnJpZW5kIGZvbyBvcGVyYXRvcnwodHlwZSBjb25zdCYgbGhzLCBmb28gY29uc3QmIHJocykgewogICAgICAgIC8vIGRvIHNvbWV0aGluZwogICAgICAgIHJldHVybiByaHM7CiAgICB9Cn07Cgp0ZW1wbGF0ZTx0eXBlIFQ+CnZvaWQgdGVzdChmb288VD4pIHt9CmludCBtYWluKCkgewogICAgdXNpbmcgZm9vX2ludCA9IGZvbzx0eXBlOjppbnRlZ2VyPjsKICAgIHVzaW5nIGZvb19zdHJpbmcgPSBmb288dHlwZTo6c3RyaW5nPjsKCiAgICAvLyB3aGF0IEkgd2FudCAodGhleSBjdXJyZW50bHkgYWxsIGRvbid0IGNvbXBpbGUpCiAgICB0ZXN0KHR5cGU6OmludGVnZXIgfCBmb29faW50KDEwKSk7IC8vIG9rCiAgICAvL3Rlc3QodHlwZTo6aW50ZWdlciB8IGZvb19pbnQoc3RkOjpzdHJpbmcoImhlbGxvIikpKTsgLy8gZXJyb3IKICAgIHRlc3QodHlwZTo6c3RyaW5nIHwgZm9vX3N0cmluZyhzdGQ6OnN0cmluZygiaGVsbG8iKSkpOyAvLyBvawogICAgLy90ZXN0KHR5cGU6OnN0cmluZyB8IGZvb19zdHJpbmcoMTApKTsgLy8gZXJyb3IKfQ==